2 Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 Locking functions for mysql.
24 Because of the new concurrent inserts, we must first get external locks
25 before getting internal locks. If we do it in the other order, the status
26 information is not up to date when called from the lock handler.
28 GENERAL DESCRIPTION OF LOCKING
30 When not using LOCK TABLES:
32 - For each SQL statement mysql_lock_tables() is called for all involved
34 - mysql_lock_tables() will call
35 table_handler->external_lock(thd,locktype) for each table.
36 This is followed by a call to thr_multi_lock() for all tables.
38 - When statement is done, we call mysql_unlock_tables().
39 This will call thr_multi_unlock() followed by
40 table_handler->external_lock(thd, F_UNLCK) for each table.
42 - Note that mysql_unlock_tables() may be called several times as
43 MySQL in some cases can free some tables earlier than others.
45 - The above is true both for normal and temporary tables.
47 - Temporary non transactional tables are never passed to thr_multi_lock()
48 and we never call external_lock(thd, F_UNLOCK) on these.
50 When using LOCK TABLES:
52 - LOCK TABLE will call mysql_lock_tables() for all tables.
53 mysql_lock_tables() will call
54 table_handler->external_lock(thd,locktype) for each table.
55 This is followed by a call to thr_multi_lock() for all tables.
57 - For each statement, we will call table_handler->start_stmt(THD)
58 to inform the table handler that we are using the table.
60 The tables used can only be tables used in LOCK TABLES or a
63 - When statement is done, we will call ha_commit_stmt(thd);
65 - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
66 tables used in LOCK TABLES
68 If table_handler->external_lock(thd, locktype) fails, we call
69 table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
70 excluding one that caused failure. That means handler must cleanup itself
71 in case external_lock() fails.
74 Change to use my_malloc() ONLY when using LOCK TABLES command or when
75 we are forced to use mysql_lock_merge.
78 #include "mysql_priv.h"
83 @defgroup Locking Locking
87 extern HASH open_cache
;
89 /* flags for get_lock_data */
90 #define GET_LOCK_UNLOCK 1
91 #define GET_LOCK_STORE_LOCKS 2
93 static MYSQL_LOCK
*get_lock_data(THD
*thd
, TABLE
**table
,uint count
,
94 uint flags
, TABLE
**write_locked
);
95 static void reset_lock_data(MYSQL_LOCK
*sql_lock
);
96 static int lock_external(THD
*thd
, TABLE
**table
,uint count
);
97 static int unlock_external(THD
*thd
, TABLE
**table
,uint count
);
98 static void print_lock_error(int error
, const char *);
105 thd The current thread.
106 tables An array of pointers to the tables to lock.
107 count The number of tables to lock.
109 MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock
110 MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY Ignore SET GLOBAL READ_ONLY
111 MYSQL_LOCK_IGNORE_FLUSH Ignore a flush tables.
112 MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered
113 or dropped tables by itself,
114 mysql_lock_tables() should
115 notify upper level and rely
116 on caller doing this.
117 need_reopen Out parameter, TRUE if some tables were altered
118 or deleted and should be reopened by caller.
121 A lock structure pointer on success.
122 NULL on error or if some tables should be reopen.
125 /* Map the return value of thr_lock to an error from errmsg.txt */
126 static int thr_lock_errno_to_mysql
[]=
127 { 0, 1, ER_LOCK_WAIT_TIMEOUT
, ER_LOCK_DEADLOCK
};
130 Perform semantic checks for mysql_lock_tables.
131 @param thd The current thread
132 @param tables The tables to lock
133 @param count The number of tables to lock
134 @param flags Lock flags
135 @return 0 if all the check passed, non zero if a check failed.
137 int mysql_lock_tables_check(THD
*thd
, TABLE
**tables
, uint count
, uint flags
)
139 bool log_table_write_query
;
143 DBUG_ENTER("mysql_lock_tables_check");
146 log_table_write_query
= (is_log_table_write_query(thd
->lex
->sql_command
)
147 || ((flags
& MYSQL_LOCK_PERF_SCHEMA
) != 0));
149 for (i
=0 ; i
<count
; i
++)
153 /* Protect against 'fake' partially initialized TABLE_SHARE */
154 DBUG_ASSERT(t
->s
->table_category
!= TABLE_UNKNOWN_CATEGORY
);
157 Table I/O to performance schema tables is performed
158 only internally by the server implementation.
159 When a user is requesting a lock, the following
160 constraints are enforced:
162 if (t
->s
->require_write_privileges() &&
163 ! log_table_write_query
)
166 A user should not be able to prevent writes,
167 or hold any type of lock in a session,
168 since this would be a DOS attack.
170 if ((t
->reginfo
.lock_type
>= TL_READ_NO_INSERT
)
171 || (thd
->lex
->sql_command
== SQLCOM_LOCK_TABLES
))
173 my_error(ER_CANT_LOCK_LOG_TABLE
, MYF(0));
178 if ((t
->s
->table_category
== TABLE_CATEGORY_SYSTEM
) &&
179 (t
->reginfo
.lock_type
>= TL_WRITE_ALLOW_WRITE
))
186 Locking of system tables is restricted:
187 locking a mix of system and non-system tables in the same lock
188 is prohibited, to prevent contention.
190 if ((system_count
> 0) && (system_count
< count
))
192 my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE
, MYF(0));
199 MYSQL_LOCK
*mysql_lock_tables(THD
*thd
, TABLE
**tables
, uint count
,
200 uint flags
, bool *need_reopen
)
202 MYSQL_LOCK
*sql_lock
;
203 TABLE
*write_lock_used
;
206 DBUG_ENTER("mysql_lock_tables");
210 if (mysql_lock_tables_check(thd
, tables
, count
, flags
))
215 if (! (sql_lock
= get_lock_data(thd
, tables
, count
, GET_LOCK_STORE_LOCKS
,
219 if (global_read_lock
&& write_lock_used
&&
220 ! (flags
& MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK
))
223 Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
224 Wait until the lock is gone
226 if (wait_if_global_read_lock(thd
, 1, 1))
228 /* Clear the lock type of all lock data to avoid reusage. */
229 reset_lock_data(sql_lock
);
230 my_free((uchar
*) sql_lock
,MYF(0));
234 if (thd
->version
!= refresh_version
)
236 /* Clear the lock type of all lock data to avoid reusage. */
237 reset_lock_data(sql_lock
);
238 my_free((uchar
*) sql_lock
,MYF(0));
243 if (!(flags
& MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY
) &&
246 !(thd
->security_ctx
->master_access
& SUPER_ACL
) &&
250 Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
251 We do not wait for READ_ONLY=0, and fail.
253 reset_lock_data(sql_lock
);
254 my_free((uchar
*) sql_lock
, MYF(0));
256 my_error(ER_OPTION_PREVENTS_STATEMENT
, MYF(0), "--read-only");
260 thd_proc_info(thd
, "System lock");
261 DBUG_PRINT("info", ("thd->proc_info %s", thd
->proc_info
));
262 if (sql_lock
->table_count
&& lock_external(thd
, sql_lock
->table
,
263 sql_lock
->table_count
))
265 /* Clear the lock type of all lock data to avoid reusage. */
266 reset_lock_data(sql_lock
);
267 my_free((uchar
*) sql_lock
,MYF(0));
271 thd_proc_info(thd
, "Table lock");
272 DBUG_PRINT("info", ("thd->proc_info %s", thd
->proc_info
));
274 /* Copy the lock data array. thr_multi_lock() reorders its contens. */
275 memcpy(sql_lock
->locks
+ sql_lock
->lock_count
, sql_lock
->locks
,
276 sql_lock
->lock_count
* sizeof(*sql_lock
->locks
));
277 /* Lock on the copied half of the lock data array. */
278 rc
= thr_lock_errno_to_mysql
[(int) thr_multi_lock(sql_lock
->locks
+
279 sql_lock
->lock_count
,
280 sql_lock
->lock_count
,
282 if (rc
> 1) /* a timeout or a deadlock */
284 if (sql_lock
->table_count
)
285 VOID(unlock_external(thd
, sql_lock
->table
, sql_lock
->table_count
));
286 my_error(rc
, MYF(0));
287 my_free((uchar
*) sql_lock
,MYF(0));
291 else if (rc
== 1) /* aborted */
294 reset_lock_data is required here. If thr_multi_lock fails it
295 resets lock type for tables, which were locked before (and
296 including) one that caused error. Lock type for other tables
299 reset_lock_data(sql_lock
);
300 thd
->some_tables_deleted
=1; // Try again
301 sql_lock
->lock_count
= 0; // Locks are already freed
303 else if (!thd
->some_tables_deleted
|| (flags
& MYSQL_LOCK_IGNORE_FLUSH
))
306 Thread was killed or lock aborted. Let upper level close all
307 used tables and retry or give error.
312 else if (!thd
->open_tables
)
314 // Only using temporary tables, no need to unlock
315 thd
->some_tables_deleted
=0;
319 thd_proc_info(thd
, 0);
321 /* some table was altered or deleted. reopen tables marked deleted */
322 mysql_unlock_tables(thd
,sql_lock
);
326 if (flags
& MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN
)
331 if (wait_for_tables(thd
))
332 break; // Couldn't open tables
334 thd_proc_info(thd
, 0);
337 thd
->send_kill_message();
340 mysql_unlock_tables(thd
,sql_lock
);
345 thd
->set_time_after_lock();
346 DBUG_RETURN (sql_lock
);
350 static int lock_external(THD
*thd
, TABLE
**tables
, uint count
)
354 DBUG_ENTER("lock_external");
356 DBUG_PRINT("info", ("count %d", count
));
357 for (i
=1 ; i
<= count
; i
++, tables
++)
359 DBUG_ASSERT((*tables
)->reginfo
.lock_type
>= TL_READ
);
360 lock_type
=F_WRLCK
; /* Lock exclusive */
361 if ((*tables
)->db_stat
& HA_READ_ONLY
||
362 ((*tables
)->reginfo
.lock_type
>= TL_READ
&&
363 (*tables
)->reginfo
.lock_type
<= TL_READ_NO_INSERT
))
366 if ((error
=(*tables
)->file
->ha_external_lock(thd
,lock_type
)))
368 print_lock_error(error
, (*tables
)->file
->table_type());
372 (*tables
)->file
->ha_external_lock(thd
, F_UNLCK
);
373 (*tables
)->current_lock
=F_UNLCK
;
379 (*tables
)->db_stat
&= ~ HA_BLOCK_LOCK
;
380 (*tables
)->current_lock
= lock_type
;
387 void mysql_unlock_tables(THD
*thd
, MYSQL_LOCK
*sql_lock
)
389 DBUG_ENTER("mysql_unlock_tables");
390 if (sql_lock
->lock_count
)
391 thr_multi_unlock(sql_lock
->locks
,sql_lock
->lock_count
);
392 if (sql_lock
->table_count
)
393 VOID(unlock_external(thd
,sql_lock
->table
,sql_lock
->table_count
));
394 my_free((uchar
*) sql_lock
,MYF(0));
399 Unlock some of the tables locked by mysql_lock_tables.
401 This will work even if get_lock_data fails (next unlock will free all)
404 void mysql_unlock_some_tables(THD
*thd
, TABLE
**table
,uint count
)
406 MYSQL_LOCK
*sql_lock
;
407 TABLE
*write_lock_used
;
408 if ((sql_lock
= get_lock_data(thd
, table
, count
, GET_LOCK_UNLOCK
,
410 mysql_unlock_tables(thd
, sql_lock
);
415 unlock all tables locked for read.
418 void mysql_unlock_read_tables(THD
*thd
, MYSQL_LOCK
*sql_lock
)
421 DBUG_ENTER("mysql_unlock_read_tables");
423 /* Move all write locks first */
424 THR_LOCK_DATA
**lock
=sql_lock
->locks
;
425 for (i
=found
=0 ; i
< sql_lock
->lock_count
; i
++)
427 if (sql_lock
->locks
[i
]->type
>= TL_WRITE_ALLOW_READ
)
429 swap_variables(THR_LOCK_DATA
*, *lock
, sql_lock
->locks
[i
]);
434 /* unlock the read locked tables */
437 thr_multi_unlock(lock
,i
-found
);
438 sql_lock
->lock_count
= found
;
441 /* Then do the same for the external locks */
442 /* Move all write locked tables first */
443 TABLE
**table
=sql_lock
->table
;
444 for (i
=found
=0 ; i
< sql_lock
->table_count
; i
++)
446 DBUG_ASSERT(sql_lock
->table
[i
]->lock_position
== i
);
447 if ((uint
) sql_lock
->table
[i
]->reginfo
.lock_type
>= TL_WRITE_ALLOW_READ
)
449 swap_variables(TABLE
*, *table
, sql_lock
->table
[i
]);
454 /* Unlock all read locked tables */
457 VOID(unlock_external(thd
,table
,i
-found
));
458 sql_lock
->table_count
=found
;
460 /* Fix the lock positions in TABLE */
461 table
= sql_lock
->table
;
463 for (i
= 0; i
< sql_lock
->table_count
; i
++)
466 tbl
->lock_position
= (uint
) (table
- sql_lock
->table
);
467 tbl
->lock_data_start
= found
;
468 found
+= tbl
->lock_count
;
476 Try to find the table in the list of locked tables.
477 In case of success, unlock the table and remove it from this list.
479 @note This function has a legacy side effect: the table is
480 unlocked even if it is not found in the locked list.
481 It's not clear if this side effect is intentional or still
482 desirable. It might lead to unmatched calls to
483 unlock_external(). Moreover, a discrepancy can be left
484 unnoticed by the storage engine, because in
485 unlock_external() we call handler::external_lock(F_UNLCK) only
486 if table->current_lock is not F_UNLCK.
488 @param thd thread context
489 @param locked list of locked tables
490 @param table the table to unlock
491 @param always_unlock specify explicitly if the legacy side
495 void mysql_lock_remove(THD
*thd
, MYSQL_LOCK
*locked
,TABLE
*table
,
498 if (always_unlock
== TRUE
)
499 mysql_unlock_some_tables(thd
, &table
, /* table count */ 1);
503 for (i
=0; i
< locked
->table_count
; i
++)
505 if (locked
->table
[i
] == table
)
507 uint j
, removed_locks
, old_tables
;
511 DBUG_ASSERT(table
->lock_position
== i
);
513 /* Unlock if not yet unlocked */
514 if (always_unlock
== FALSE
)
515 mysql_unlock_some_tables(thd
, &table
, /* table count */ 1);
517 /* Decrement table_count in advance, making below expressions easier */
518 old_tables
= --locked
->table_count
;
520 /* The table has 'removed_locks' lock data elements in locked->locks */
521 removed_locks
= table
->lock_count
;
523 /* Move down all table pointers above 'i'. */
524 bmove((char*) (locked
->table
+i
),
525 (char*) (locked
->table
+i
+1),
526 (old_tables
- i
) * sizeof(TABLE
*));
528 lock_data_end
= table
->lock_data_start
+ table
->lock_count
;
529 /* Move down all lock data pointers above 'table->lock_data_end-1' */
530 bmove((char*) (locked
->locks
+ table
->lock_data_start
),
531 (char*) (locked
->locks
+ lock_data_end
),
532 (locked
->lock_count
- lock_data_end
) *
533 sizeof(THR_LOCK_DATA
*));
536 Fix moved table elements.
537 lock_position is the index in the 'locked->table' array,
538 it must be fixed by one.
539 table->lock_data_start is pointer to the lock data for this table
540 in the 'locked->locks' array, they must be fixed by 'removed_locks',
541 the lock data count of the removed table.
543 for (j
= i
; j
< old_tables
; j
++)
545 tbl
= locked
->table
[j
];
546 tbl
->lock_position
--;
547 DBUG_ASSERT(tbl
->lock_position
== j
);
548 tbl
->lock_data_start
-= removed_locks
;
551 /* Finally adjust lock_count. */
552 locked
->lock_count
-= removed_locks
;
559 /* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
561 void mysql_lock_downgrade_write(THD
*thd
, TABLE
*table
,
562 thr_lock_type new_lock_type
)
565 TABLE
*write_lock_used
;
566 if ((locked
= get_lock_data(thd
, &table
, 1, GET_LOCK_UNLOCK
,
569 for (uint i
=0; i
< locked
->lock_count
; i
++)
570 thr_downgrade_write_lock(locked
->locks
[i
], new_lock_type
);
571 my_free((uchar
*) locked
,MYF(0));
576 /** Abort all other threads waiting to get lock in table. */
578 void mysql_lock_abort(THD
*thd
, TABLE
*table
, bool upgrade_lock
)
581 TABLE
*write_lock_used
;
582 DBUG_ENTER("mysql_lock_abort");
584 if ((locked
= get_lock_data(thd
, &table
, 1, GET_LOCK_UNLOCK
,
587 for (uint i
=0; i
< locked
->lock_count
; i
++)
588 thr_abort_locks(locked
->locks
[i
]->lock
, upgrade_lock
);
589 my_free((uchar
*) locked
,MYF(0));
596 Abort one thread / table combination.
598 @param thd Thread handler
599 @param table Table that should be removed from lock queue
602 0 Table was not locked by another thread
604 1 Table was locked by at least one other thread
607 bool mysql_lock_abort_for_thread(THD
*thd
, TABLE
*table
)
610 TABLE
*write_lock_used
;
612 DBUG_ENTER("mysql_lock_abort_for_thread");
614 if ((locked
= get_lock_data(thd
, &table
, 1, GET_LOCK_UNLOCK
,
617 for (uint i
=0; i
< locked
->lock_count
; i
++)
619 if (thr_abort_locks_for_thread(locked
->locks
[i
]->lock
,
620 table
->in_use
->thread_id
))
623 my_free((uchar
*) locked
,MYF(0));
629 MYSQL_LOCK
*mysql_lock_merge(MYSQL_LOCK
*a
,MYSQL_LOCK
*b
)
631 MYSQL_LOCK
*sql_lock
;
632 TABLE
**table
, **end_table
;
633 DBUG_ENTER("mysql_lock_merge");
635 if (!(sql_lock
= (MYSQL_LOCK
*)
636 my_malloc(sizeof(*sql_lock
)+
637 sizeof(THR_LOCK_DATA
*)*(a
->lock_count
+b
->lock_count
)+
638 sizeof(TABLE
*)*(a
->table_count
+b
->table_count
),MYF(MY_WME
))))
639 DBUG_RETURN(0); // Fatal error
640 sql_lock
->lock_count
=a
->lock_count
+b
->lock_count
;
641 sql_lock
->table_count
=a
->table_count
+b
->table_count
;
642 sql_lock
->locks
=(THR_LOCK_DATA
**) (sql_lock
+1);
643 sql_lock
->table
=(TABLE
**) (sql_lock
->locks
+sql_lock
->lock_count
);
644 memcpy(sql_lock
->locks
,a
->locks
,a
->lock_count
*sizeof(*a
->locks
));
645 memcpy(sql_lock
->locks
+a
->lock_count
,b
->locks
,
646 b
->lock_count
*sizeof(*b
->locks
));
647 memcpy(sql_lock
->table
,a
->table
,a
->table_count
*sizeof(*a
->table
));
648 memcpy(sql_lock
->table
+a
->table_count
,b
->table
,
649 b
->table_count
*sizeof(*b
->table
));
652 Now adjust lock_position and lock_data_start for all objects that was
653 moved in 'b' (as there is now all objects in 'a' before these).
655 for (table
= sql_lock
->table
+ a
->table_count
,
656 end_table
= table
+ b
->table_count
;
660 (*table
)->lock_position
+= a
->table_count
;
661 (*table
)->lock_data_start
+= a
->lock_count
;
664 /* Delete old, not needed locks */
665 my_free((uchar
*) a
,MYF(0));
666 my_free((uchar
*) b
,MYF(0));
667 DBUG_RETURN(sql_lock
);
672 Find duplicate lock in tables.
674 Temporary tables are ignored here like they are ignored in
675 get_lock_data(). If we allow two opens on temporary tables later,
676 both functions should be checked.
678 @param thd The current thread.
679 @param needle The table to check for duplicate lock.
680 @param haystack The list of tables to search for the dup lock.
683 This is mainly meant for MERGE tables in INSERT ... SELECT
684 situations. The 'real', underlying tables can be found only after
685 the MERGE tables are opened. This function assumes that the tables are
689 NULL No duplicate lock found.
691 !NULL First table from 'haystack' that matches a lock on 'needle'.
694 TABLE_LIST
*mysql_lock_have_duplicate(THD
*thd
, TABLE_LIST
*needle
,
695 TABLE_LIST
*haystack
)
700 THR_LOCK_DATA
**lock_locks
;
701 THR_LOCK_DATA
**table_lock_data
;
702 THR_LOCK_DATA
**end_data
;
703 THR_LOCK_DATA
**lock_data2
;
704 THR_LOCK_DATA
**end_data2
;
705 DBUG_ENTER("mysql_lock_have_duplicate");
708 Table may not be defined for derived or view tables.
709 Table may not be part of a lock for delayed operations.
711 if (! (table
= needle
->table
) || ! table
->lock_count
)
714 /* A temporary table does not have locks. */
715 if (table
->s
->tmp_table
== NON_TRANSACTIONAL_TMP_TABLE
)
718 /* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
719 if (! (mylock
= thd
->lock
? thd
->lock
: thd
->locked_tables
))
722 /* If we have less than two tables, we cannot have duplicates. */
723 if (mylock
->table_count
< 2)
726 lock_locks
= mylock
->locks
;
728 /* Prepare table related variables that don't change in loop. */
729 DBUG_ASSERT((table
->lock_position
< mylock
->table_count
) &&
730 (table
== mylock
->table
[table
->lock_position
]));
731 table_lock_data
= lock_locks
+ table
->lock_data_start
;
732 end_data
= table_lock_data
+ table
->lock_count
;
734 for (; haystack
; haystack
= haystack
->next_global
)
736 if (haystack
->placeholder())
738 table2
= haystack
->table
;
739 if (table2
->s
->tmp_table
== NON_TRANSACTIONAL_TMP_TABLE
)
742 /* All tables in list must be in lock. */
743 DBUG_ASSERT((table2
->lock_position
< mylock
->table_count
) &&
744 (table2
== mylock
->table
[table2
->lock_position
]));
746 for (lock_data2
= lock_locks
+ table2
->lock_data_start
,
747 end_data2
= lock_data2
+ table2
->lock_count
;
748 lock_data2
< end_data2
;
751 THR_LOCK_DATA
**lock_data
;
752 THR_LOCK
*lock2
= (*lock_data2
)->lock
;
754 for (lock_data
= table_lock_data
;
755 lock_data
< end_data
;
758 if ((*lock_data
)->lock
== lock2
)
760 DBUG_PRINT("info", ("haystack match: '%s'", haystack
->table_name
));
761 DBUG_RETURN(haystack
);
768 DBUG_PRINT("info", ("no duplicate found"));
773 /** Unlock a set of external. */
775 static int unlock_external(THD
*thd
, TABLE
**table
,uint count
)
777 int error
,error_code
;
778 DBUG_ENTER("unlock_external");
783 if ((*table
)->current_lock
!= F_UNLCK
)
785 (*table
)->current_lock
= F_UNLCK
;
786 if ((error
=(*table
)->file
->ha_external_lock(thd
, F_UNLCK
)))
789 print_lock_error(error_code
, (*table
)->file
->table_type());
794 DBUG_RETURN(error_code
);
799 Get lock structures from table structs and initialize locks.
801 @param thd Thread handler
802 @param table_ptr Pointer to tables that should be locks
804 - GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
805 - GET_LOCK_STORE_LOCKS : Store lock info in TABLE
806 @param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
809 static MYSQL_LOCK
*get_lock_data(THD
*thd
, TABLE
**table_ptr
, uint count
,
810 uint flags
, TABLE
**write_lock_used
)
812 uint i
,tables
,lock_count
;
813 MYSQL_LOCK
*sql_lock
;
814 THR_LOCK_DATA
**locks
, **locks_buf
, **locks_start
;
815 TABLE
**to
, **table_buf
;
816 DBUG_ENTER("get_lock_data");
818 DBUG_ASSERT((flags
== GET_LOCK_UNLOCK
) || (flags
== GET_LOCK_STORE_LOCKS
));
820 DBUG_PRINT("info", ("count %d", count
));
822 for (i
=tables
=lock_count
=0 ; i
< count
; i
++)
824 TABLE
*t
= table_ptr
[i
];
826 if (t
->s
->tmp_table
!= NON_TRANSACTIONAL_TMP_TABLE
)
828 tables
+= t
->file
->lock_count();
834 Allocating twice the number of pointers for lock data for use in
835 thr_mulit_lock(). This function reorders the lock data, but cannot
836 update the table values. So the second part of the array is copied
837 from the first part immediately before calling thr_multi_lock().
839 if (!(sql_lock
= (MYSQL_LOCK
*)
840 my_malloc(sizeof(*sql_lock
) +
841 sizeof(THR_LOCK_DATA
*) * tables
* 2 +
842 sizeof(table_ptr
) * lock_count
,
845 locks
= locks_buf
= sql_lock
->locks
= (THR_LOCK_DATA
**) (sql_lock
+ 1);
846 to
= table_buf
= sql_lock
->table
= (TABLE
**) (locks
+ tables
* 2);
847 sql_lock
->table_count
=lock_count
;
849 for (i
=0 ; i
< count
; i
++)
852 enum thr_lock_type lock_type
;
854 if ((table
=table_ptr
[i
])->s
->tmp_table
== NON_TRANSACTIONAL_TMP_TABLE
)
856 lock_type
= table
->reginfo
.lock_type
;
857 DBUG_ASSERT(lock_type
!= TL_WRITE_DEFAULT
&& lock_type
!= TL_READ_DEFAULT
);
858 if (lock_type
>= TL_WRITE_ALLOW_WRITE
)
860 *write_lock_used
=table
;
861 if (table
->db_stat
& HA_READ_ONLY
)
863 my_error(ER_OPEN_AS_READONLY
,MYF(0),table
->alias
);
864 /* Clear the lock type of the lock data that are stored already. */
865 sql_lock
->lock_count
= (uint
) (locks
- sql_lock
->locks
);
866 reset_lock_data(sql_lock
);
867 my_free((uchar
*) sql_lock
,MYF(0));
871 THR_LOCK_DATA
**org_locks
= locks
;
873 locks
= table
->file
->store_lock(thd
, locks
,
874 (flags
& GET_LOCK_UNLOCK
) ? TL_IGNORE
:
876 if (flags
& GET_LOCK_STORE_LOCKS
)
878 table
->lock_position
= (uint
) (to
- table_buf
);
879 table
->lock_data_start
= (uint
) (locks_start
- locks_buf
);
880 table
->lock_count
= (uint
) (locks
- locks_start
);
884 for ( ; org_locks
!= locks
; org_locks
++)
885 (*org_locks
)->debug_print_param
= (void *) table
;
888 We do not use 'tables', because there are cases where store_lock()
889 returns less locks than lock_count() claimed. This can happen when
890 a FLUSH TABLES tries to abort locks from a MERGE table of another
891 thread. When that thread has just opened the table, but not yet
892 attached its children, it cannot return the locks. lock_count()
893 always returns the number of locks that an attached table has.
894 This is done to avoid the reverse situation: If lock_count() would
895 return 0 for a non-attached MERGE table, and that table becomes
896 attached between the calls to lock_count() and store_lock(), then
897 we would have allocated too little memory for the lock data. Now
898 we may allocate too much, but better safe than memory overrun.
899 And in the FLUSH case, the memory is released quickly anyway.
901 sql_lock
->lock_count
= locks
- locks_buf
;
902 DBUG_PRINT("info", ("sql_lock->table_count %d sql_lock->lock_count %d",
903 sql_lock
->table_count
, sql_lock
->lock_count
));
904 DBUG_RETURN(sql_lock
);
909 Reset lock type in lock data.
911 After a locking error we want to quit the locking of the table(s).
912 The test case in the bug report for Bug #18544 has the following
914 -# Locking error in lock_external() due to InnoDB timeout.
915 -# Locking error in get_lock_data() due to missing write permission.
916 -# Locking error in wait_if_global_read_lock() due to lock conflict.
918 In all these cases we have already set the lock type into the lock
919 data of the open table(s). If the table(s) are in the open table
920 cache, they could be reused with the non-zero lock type set. This
921 could lead to ignoring a different lock type with the next lock.
923 Clear the lock type of all lock data. This ensures that the next
924 lock request will set its lock type properly.
926 @param sql_lock The MySQL lock.
929 static void reset_lock_data(MYSQL_LOCK
*sql_lock
)
931 THR_LOCK_DATA
**ldata
;
932 THR_LOCK_DATA
**ldata_end
;
934 for (ldata
= sql_lock
->locks
, ldata_end
= ldata
+ sql_lock
->lock_count
;
938 /* Reset lock type. */
939 (*ldata
)->type
= TL_UNLOCK
;
944 /*****************************************************************************
945 Lock table based on the name.
946 This is used when we need total access to a closed, not open table
947 *****************************************************************************/
950 Lock and wait for the named lock.
952 @param thd Thread handler
953 @param table_list Lock first table in this list
957 Works together with global read lock.
965 int lock_and_wait_for_table_name(THD
*thd
, TABLE_LIST
*table_list
)
969 DBUG_ENTER("lock_and_wait_for_table_name");
971 if (wait_if_global_read_lock(thd
, 0, 1))
973 VOID(pthread_mutex_lock(&LOCK_open
));
974 if ((lock_retcode
= lock_table_name(thd
, table_list
, TRUE
)) < 0)
976 if (lock_retcode
&& wait_for_locked_table_names(thd
, table_list
))
978 unlock_table_name(thd
, table_list
);
984 pthread_mutex_unlock(&LOCK_open
);
985 start_waiting_global_read_lock(thd
);
991 Put a not open table with an old refresh version in the table cache.
993 @param thd Thread handler
994 @param table_list Lock first table in this list
995 @param check_in_use Do we need to check if table already in use by us
998 One must have a lock on LOCK_open!
1001 If you are going to update the table, you should use
1002 lock_and_wait_for_table_name instead of this function as this works
1003 together with 'FLUSH TABLES WITH READ LOCK'
1006 This will force any other threads that uses the table to release it
1007 as soon as possible.
1014 > 0 table locked, but someone is using it
1017 int lock_table_name(THD
*thd
, TABLE_LIST
*table_list
, bool check_in_use
)
1020 char key
[MAX_DBKEY_LENGTH
];
1021 char *db
= table_list
->db
;
1023 HASH_SEARCH_STATE state
;
1024 DBUG_ENTER("lock_table_name");
1025 DBUG_PRINT("enter",("db: %s name: %s", db
, table_list
->table_name
));
1027 key_length
= create_table_def_key(thd
, key
, table_list
, 0);
1031 /* Only insert the table if we haven't insert it already */
1032 for (table
=(TABLE
*) hash_first(&open_cache
, (uchar
*)key
,
1033 key_length
, &state
);
1035 table
= (TABLE
*) hash_next(&open_cache
,(uchar
*) key
,
1036 key_length
, &state
))
1038 if (table
->in_use
== thd
)
1040 DBUG_PRINT("info", ("Table is in use"));
1041 table
->s
->version
= 0; // Ensure no one can use this
1042 table
->locked_by_name
= 1;
1048 if (!(table
= table_cache_insert_placeholder(thd
, key
, key_length
)))
1051 table_list
->table
=table
;
1053 /* Return 1 if table is in use */
1054 DBUG_RETURN(test(remove_table_from_cache(thd
, db
, table_list
->table_name
,
1055 check_in_use
? RTFC_NO_FLAG
: RTFC_WAIT_OTHER_THREAD_FLAG
)));
1059 void unlock_table_name(THD
*thd
, TABLE_LIST
*table_list
)
1061 if (table_list
->table
)
1063 hash_delete(&open_cache
, (uchar
*) table_list
->table
);
1064 broadcast_refresh();
1069 static bool locked_named_table(THD
*thd
, TABLE_LIST
*table_list
)
1071 for (; table_list
; table_list
=table_list
->next_local
)
1073 TABLE
*table
= table_list
->table
;
1076 TABLE
*save_next
= table
->next
;
1079 result
= table_is_used(table_list
->table
, 0);
1080 table
->next
= save_next
;
1085 return 0; // All tables are locked
1089 bool wait_for_locked_table_names(THD
*thd
, TABLE_LIST
*table_list
)
1092 DBUG_ENTER("wait_for_locked_table_names");
1094 safe_mutex_assert_owner(&LOCK_open
);
1096 while (locked_named_table(thd
,table_list
))
1103 wait_for_condition(thd
, &LOCK_open
, &COND_refresh
);
1104 pthread_mutex_lock(&LOCK_open
);
1106 DBUG_RETURN(result
);
1111 Lock all tables in list with a name lock.
1114 - One must have a lock on LOCK_open when calling this
1116 @param thd Thread handle
1117 @param table_list Names of tables to lock
1120 If you are just locking one table, you should use
1121 lock_and_wait_for_table_name().
1126 1 Fatal error (end of memory ?)
1129 bool lock_table_names(THD
*thd
, TABLE_LIST
*table_list
)
1131 bool got_all_locks
=1;
1132 TABLE_LIST
*lock_table
;
1134 for (lock_table
= table_list
; lock_table
; lock_table
= lock_table
->next_local
)
1137 if ((got_lock
=lock_table_name(thd
,lock_table
, TRUE
)) < 0)
1138 goto end
; // Fatal error
1140 got_all_locks
=0; // Someone is using table
1143 /* If some table was in use, wait until we got the lock */
1144 if (!got_all_locks
&& wait_for_locked_table_names(thd
, table_list
))
1149 unlock_table_names(thd
, table_list
, lock_table
);
1155 Unlock all tables in list with a name lock.
1157 @param thd Thread handle.
1158 @param table_list Names of tables to lock.
1161 This function needs to be protected by LOCK_open. If we're
1162 under LOCK TABLES, this function does not work as advertised. Namely,
1163 it does not exclude other threads from using this table and does not
1164 put an exclusive name lock on this table into the table cache.
1166 @see lock_table_names
1167 @see unlock_table_names
1169 @retval TRUE An error occured.
1170 @retval FALSE Name lock successfully acquired.
1173 bool lock_table_names_exclusively(THD
*thd
, TABLE_LIST
*table_list
)
1175 if (lock_table_names(thd
, table_list
))
1179 Upgrade the table name locks from semi-exclusive to exclusive locks.
1181 for (TABLE_LIST
*table
= table_list
; table
; table
= table
->next_global
)
1184 table
->table
->open_placeholder
= 1;
1191 Test is 'table' is protected by an exclusive name lock.
1193 @param[in] thd The current thread handler
1194 @param[in] table_list Table container containing the single table to be
1197 @note Needs to be protected by LOCK_open mutex.
1199 @return Error status code
1200 @retval TRUE Table is protected
1201 @retval FALSE Table is not protected
1205 is_table_name_exclusively_locked_by_this_thread(THD
*thd
,
1206 TABLE_LIST
*table_list
)
1208 char key
[MAX_DBKEY_LENGTH
];
1211 key_length
= create_table_def_key(thd
, key
, table_list
, 0);
1213 return is_table_name_exclusively_locked_by_this_thread(thd
, (uchar
*)key
,
1219 Test is 'table key' is protected by an exclusive name lock.
1221 @param[in] thd The current thread handler.
1223 @param[in] key_length
1225 @note Needs to be protected by LOCK_open mutex
1227 @retval TRUE Table is protected
1228 @retval FALSE Table is not protected
1232 is_table_name_exclusively_locked_by_this_thread(THD
*thd
, uchar
*key
,
1235 HASH_SEARCH_STATE state
;
1238 for (table
= (TABLE
*) hash_first(&open_cache
, key
,
1239 key_length
, &state
);
1241 table
= (TABLE
*) hash_next(&open_cache
, key
,
1242 key_length
, &state
))
1244 if (table
->in_use
== thd
&&
1245 table
->open_placeholder
== 1 &&
1246 table
->s
->version
== 0)
1254 Unlock all tables in list with a name lock.
1259 table_list Names of tables to unlock
1261 last_table Don't unlock any tables after this one.
1262 (default 0, which will unlock all tables)
1265 One must have a lock on LOCK_open when calling this.
1268 This function will broadcast refresh signals to inform other threads
1269 that the name locks are removed.
1274 1 Fatal error (end of memory ?)
1277 void unlock_table_names(THD
*thd
, TABLE_LIST
*table_list
,
1278 TABLE_LIST
*last_table
)
1280 DBUG_ENTER("unlock_table_names");
1281 for (TABLE_LIST
*table
= table_list
;
1282 table
!= last_table
;
1283 table
= table
->next_local
)
1284 unlock_table_name(thd
,table
);
1285 broadcast_refresh();
1290 static void print_lock_error(int error
, const char *table
)
1293 DBUG_ENTER("print_lock_error");
1296 case HA_ERR_LOCK_WAIT_TIMEOUT
:
1297 textno
=ER_LOCK_WAIT_TIMEOUT
;
1299 case HA_ERR_READ_ONLY_TRANSACTION
:
1300 textno
=ER_READ_ONLY_TRANSACTION
;
1302 case HA_ERR_LOCK_DEADLOCK
:
1303 textno
=ER_LOCK_DEADLOCK
;
1305 case HA_ERR_WRONG_COMMAND
:
1306 textno
=ER_ILLEGAL_HA
;
1309 textno
=ER_CANT_LOCK
;
1313 if ( textno
== ER_ILLEGAL_HA
)
1314 my_error(textno
, MYF(ME_BELL
+ME_OLDWIN
+ME_WAITTANG
), table
);
1316 my_error(textno
, MYF(ME_BELL
+ME_OLDWIN
+ME_WAITTANG
), error
);
1322 /****************************************************************************
1323 Handling of global read locks
1325 Taking the global read lock is TWO steps (2nd step is optional; without
1326 it, COMMIT of existing transactions will be allowed):
1327 lock_global_read_lock() THEN make_global_read_lock_block_commit().
1329 The global locks are handled through the global variables:
1331 count of threads which have the global read lock (i.e. have completed at
1332 least the first step above)
1333 global_read_lock_blocks_commit
1334 count of threads which have the global read lock and block
1335 commits (i.e. are in or have completed the second step above)
1336 waiting_for_read_lock
1337 count of threads which want to take a global read lock but cannot
1338 protect_against_global_read_lock
1339 count of threads which have set protection against global read lock.
1341 access to them is protected with a mutex LOCK_global_read_lock
1343 (XXX: one should never take LOCK_open if LOCK_global_read_lock is
1344 taken, otherwise a deadlock may occur. Other mutexes could be a
1345 problem too - grep the code for global_read_lock if you want to use
1346 any other mutex here) Also one must not hold LOCK_open when calling
1347 wait_if_global_read_lock(). When the thread with the global read lock
1348 tries to close its tables, it needs to take LOCK_open in
1349 close_thread_table().
1351 How blocking of threads by global read lock is achieved: that's
1352 advisory. Any piece of code which should be blocked by global read lock must
1353 be designed like this:
1354 - call to wait_if_global_read_lock(). When this returns 0, no global read
1355 lock is owned; if argument abort_on_refresh was 0, none can be obtained.
1357 - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
1358 allow other threads to get the global read lock. I.e. removal of the
1360 (Note: it's a bit like an implementation of rwlock).
1362 [ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
1363 no better descriptive way ]
1365 Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
1366 to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
1369 Why getting the global read lock is two steps and not one. Because FLUSH
1370 TABLES WITH READ LOCK needs to insert one other step between the two:
1371 flushing tables. So the order is
1372 1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
1374 2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
1375 currently opened and being updated to close (so it's possible that there is
1376 a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
1378 3) make_global_read_lock_block_commit().
1379 If we have merged 1) and 3) into 1), we would have had this deadlock:
1380 imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
1382 thd1: SELECT * FROM t FOR UPDATE;
1383 thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
1384 thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
1385 table instance of thd2
1386 thd1: COMMIT; # blocked by thd3.
1387 thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
1389 Note that we need to support that one thread does
1390 FLUSH TABLES WITH READ LOCK; and then COMMIT;
1391 (that's what innobackup does, for some good reason).
1392 So in this exceptional case the COMMIT should not be blocked by the FLUSH
1393 TABLES WITH READ LOCK.
1395 ****************************************************************************/
1397 volatile uint global_read_lock
=0;
1398 volatile uint global_read_lock_blocks_commit
=0;
1399 static volatile uint protect_against_global_read_lock
=0;
1400 static volatile uint waiting_for_read_lock
=0;
1402 #define GOT_GLOBAL_READ_LOCK 1
1403 #define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1405 bool lock_global_read_lock(THD
*thd
)
1407 DBUG_ENTER("lock_global_read_lock");
1409 if (!thd
->global_read_lock
)
1411 const char *old_message
;
1412 (void) pthread_mutex_lock(&LOCK_global_read_lock
);
1413 old_message
=thd
->enter_cond(&COND_global_read_lock
, &LOCK_global_read_lock
,
1414 "Waiting to get readlock");
1416 ("waiting_for: %d protect_against: %d",
1417 waiting_for_read_lock
, protect_against_global_read_lock
));
1419 waiting_for_read_lock
++;
1420 while (protect_against_global_read_lock
&& !thd
->killed
)
1421 pthread_cond_wait(&COND_global_read_lock
, &LOCK_global_read_lock
);
1422 waiting_for_read_lock
--;
1425 thd
->exit_cond(old_message
);
1428 thd
->global_read_lock
= GOT_GLOBAL_READ_LOCK
;
1430 thd
->exit_cond(old_message
); // this unlocks LOCK_global_read_lock
1433 We DON'T set global_read_lock_blocks_commit now, it will be set after
1434 tables are flushed (as the present function serves for FLUSH TABLES WITH
1435 READ LOCK only). Doing things in this order is necessary to avoid
1436 deadlocks (we must allow COMMIT until all tables are closed; we should not
1437 forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1438 UPDATE and one does FLUSH TABLES WITH READ LOCK).
1444 void unlock_global_read_lock(THD
*thd
)
1447 DBUG_ENTER("unlock_global_read_lock");
1449 ("global_read_lock: %u global_read_lock_blocks_commit: %u",
1450 global_read_lock
, global_read_lock_blocks_commit
));
1452 pthread_mutex_lock(&LOCK_global_read_lock
);
1453 tmp
= --global_read_lock
;
1454 if (thd
->global_read_lock
== MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT
)
1455 --global_read_lock_blocks_commit
;
1456 pthread_mutex_unlock(&LOCK_global_read_lock
);
1457 /* Send the signal outside the mutex to avoid a context switch */
1460 DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock"));
1461 pthread_cond_broadcast(&COND_global_read_lock
);
1463 thd
->global_read_lock
= 0;
1468 #define must_wait (global_read_lock && \
1470 global_read_lock_blocks_commit))
1472 bool wait_if_global_read_lock(THD
*thd
, bool abort_on_refresh
,
1475 const char *UNINIT_VAR(old_message
);
1476 bool result
= 0, need_exit_cond
;
1477 DBUG_ENTER("wait_if_global_read_lock");
1480 Assert that we do not own LOCK_open. If we would own it, other
1481 threads could not close their tables. This would make a pretty
1484 safe_mutex_assert_not_owner(&LOCK_open
);
1486 (void) pthread_mutex_lock(&LOCK_global_read_lock
);
1487 if ((need_exit_cond
= must_wait
))
1489 if (thd
->global_read_lock
) // This thread had the read locks
1492 my_message(ER_CANT_UPDATE_WITH_READLOCK
,
1493 ER(ER_CANT_UPDATE_WITH_READLOCK
), MYF(0));
1494 (void) pthread_mutex_unlock(&LOCK_global_read_lock
);
1496 We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
1497 This allowance is needed to not break existing versions of innobackup
1498 which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
1500 DBUG_RETURN(is_not_commit
);
1502 old_message
=thd
->enter_cond(&COND_global_read_lock
, &LOCK_global_read_lock
,
1503 "Waiting for release of readlock");
1504 while (must_wait
&& ! thd
->killed
&&
1505 (!abort_on_refresh
|| thd
->version
== refresh_version
))
1507 DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
1508 (void) pthread_cond_wait(&COND_global_read_lock
, &LOCK_global_read_lock
);
1509 DBUG_PRINT("signal", ("Got COND_global_read_lock"));
1514 if (!abort_on_refresh
&& !result
)
1515 protect_against_global_read_lock
++;
1517 The following is only true in case of a global read locks (which is rare)
1518 and if old_message is set
1520 if (unlikely(need_exit_cond
))
1521 thd
->exit_cond(old_message
); // this unlocks LOCK_global_read_lock
1523 pthread_mutex_unlock(&LOCK_global_read_lock
);
1524 DBUG_RETURN(result
);
1528 void start_waiting_global_read_lock(THD
*thd
)
1531 DBUG_ENTER("start_waiting_global_read_lock");
1532 if (unlikely(thd
->global_read_lock
))
1534 (void) pthread_mutex_lock(&LOCK_global_read_lock
);
1535 DBUG_ASSERT(protect_against_global_read_lock
);
1536 tmp
= (!--protect_against_global_read_lock
&&
1537 (waiting_for_read_lock
|| global_read_lock_blocks_commit
));
1538 (void) pthread_mutex_unlock(&LOCK_global_read_lock
);
1540 pthread_cond_broadcast(&COND_global_read_lock
);
1545 bool make_global_read_lock_block_commit(THD
*thd
)
1548 const char *old_message
;
1549 DBUG_ENTER("make_global_read_lock_block_commit");
1551 If we didn't succeed lock_global_read_lock(), or if we already suceeded
1552 make_global_read_lock_block_commit(), do nothing.
1554 if (thd
->global_read_lock
!= GOT_GLOBAL_READ_LOCK
)
1556 pthread_mutex_lock(&LOCK_global_read_lock
);
1557 /* increment this BEFORE waiting on cond (otherwise race cond) */
1558 global_read_lock_blocks_commit
++;
1559 /* For testing we set up some blocking, to see if we can be killed */
1560 DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1561 protect_against_global_read_lock
++;);
1562 old_message
= thd
->enter_cond(&COND_global_read_lock
, &LOCK_global_read_lock
,
1563 "Waiting for all running commits to finish");
1564 while (protect_against_global_read_lock
&& !thd
->killed
)
1565 pthread_cond_wait(&COND_global_read_lock
, &LOCK_global_read_lock
);
1566 DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1567 protect_against_global_read_lock
--;);
1568 if ((error
= test(thd
->killed
)))
1569 global_read_lock_blocks_commit
--; // undo what we did
1571 thd
->global_read_lock
= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT
;
1572 thd
->exit_cond(old_message
); // this unlocks LOCK_global_read_lock
1578 Broadcast COND_refresh and COND_global_read_lock.
1580 Due to a bug in a threading library it could happen that a signal
1581 did not reach its target. A condition for this was that the same
1582 condition variable was used with different mutexes in
1583 pthread_cond_wait(). Some time ago we changed LOCK_open to
1584 LOCK_global_read_lock in global read lock handling. So COND_refresh
1585 was used with LOCK_open and LOCK_global_read_lock.
1587 We did now also change from COND_refresh to COND_global_read_lock
1588 in global read lock handling. But now it is necessary to signal
1589 both conditions at the same time.
1592 When signalling COND_global_read_lock within the global read lock
1593 handling, it is not necessary to also signal COND_refresh.
1596 void broadcast_refresh(void)
1598 VOID(pthread_cond_broadcast(&COND_refresh
));
1599 VOID(pthread_cond_broadcast(&COND_global_read_lock
));
1603 @} (end of group Locking)