~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/lock.cc

  • Committer: Brian Aker
  • Date: 2010-10-20 20:25:52 UTC
  • mto: (1864.2.1 merge)
  • mto: This revision was merged to the branch mainline in revision 1865.
  • Revision ID: brian@tangent.org-20101020202552-51y5sz5ledoxbp7t
Add support for --with-valgrind

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
 
17
17
/**
34
34
      This is followed by a call to thr_multi_lock() for all tables.
35
35
 
36
36
  - When statement is done, we call mysql_unlock_tables().
37
 
    This will call thr_multi_unlock() followed by
 
37
    This will call DrizzleLock::unlock() followed by
38
38
    table_handler->external_lock(session, F_UNLCK) for each table.
39
39
 
40
40
  - Note that mysql_unlock_tables() may be called several times as
82
82
#include <drizzled/lock.h>
83
83
#include "drizzled/pthread_globals.h"
84
84
#include "drizzled/internal/my_sys.h"
 
85
#include "drizzled/pthread_globals.h"
85
86
 
86
87
#include <set>
87
88
#include <vector>
88
89
#include <algorithm>
89
90
#include <functional>
90
91
 
 
92
#include <boost/thread/shared_mutex.hpp>
 
93
#include <boost/thread/condition_variable.hpp>
 
94
 
91
95
using namespace std;
92
96
 
93
97
namespace drizzled
94
98
{
95
99
 
 
100
static boost::mutex LOCK_global_read_lock;
 
101
static boost::condition_variable_any COND_global_read_lock;
 
102
 
96
103
/**
97
104
  @defgroup Locking Locking
98
105
  @{
99
106
*/
100
107
 
101
 
extern HASH open_cache;
102
 
 
103
 
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table,
104
 
                                   uint32_t count,
105
 
                                   bool should_lock, Table **write_locked);
 
108
static DrizzleLock *get_lock_data(Session *session, Table **table,
 
109
                                  uint32_t count,
 
110
                                  bool should_lock, Table **write_locked);
106
111
static int lock_external(Session *session, Table **table,uint32_t count);
107
112
static int unlock_external(Session *session, Table **table,uint32_t count);
108
113
static void print_lock_error(int error, const char *);
156
161
        lock request will set its lock type properly.
157
162
*/
158
163
 
159
 
static void reset_lock_data_and_free(DRIZZLE_LOCK **mysql_lock)
 
164
static void reset_lock_data_and_free(DrizzleLock **mysql_lock)
160
165
{
161
 
  DRIZZLE_LOCK *sql_lock= *mysql_lock;
162
 
  THR_LOCK_DATA **ldata, **ldata_end;
163
 
 
164
 
  /* Clear the lock type of all lock data to avoid reusage. */
165
 
  for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
166
 
       ldata < ldata_end;
167
 
       ldata++)
168
 
  {
169
 
    /* Reset lock type. */
170
 
    (*ldata)->type= TL_UNLOCK;
171
 
  }
172
 
  free((unsigned char*) sql_lock);
 
166
  DrizzleLock *sql_lock= *mysql_lock;
 
167
  sql_lock->reset();
 
168
  delete sql_lock;
173
169
  *mysql_lock= 0;
174
170
}
175
171
 
176
 
 
177
 
DRIZZLE_LOCK *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
 
172
void DrizzleLock::reset(void)
 
173
{
 
174
  for (std::vector<THR_LOCK_DATA *>::iterator iter= locks.begin(); iter != locks.end(); iter++)
 
175
  {
 
176
    (*iter)->type= TL_UNLOCK;
 
177
  }
 
178
}
 
179
 
 
180
 
 
181
DrizzleLock *mysql_lock_tables(Session *session, Table **tables, uint32_t count,
178
182
                                uint32_t flags, bool *need_reopen)
179
183
{
180
 
  DRIZZLE_LOCK *sql_lock;
 
184
  DrizzleLock *sql_lock;
181
185
  Table *write_lock_used;
182
186
  vector<plugin::StorageEngine *> involved_engines;
183
187
  int rc;
223
227
      set<size_t> involved_slots;
224
228
      for (size_t x= 1; x <= num_tables; x++, tables++)
225
229
      {
226
 
        engine= (*tables)->cursor->engine;
 
230
        engine= (*tables)->cursor->getEngine();
227
231
        if (involved_slots.count(engine->getId()) > 0)
228
232
          continue; /* already added to involved engines */
229
233
        involved_engines.push_back(engine);
242
246
     * of the type of lock that Drizzle intends to take on a 
243
247
     * specific table.
244
248
     */
245
 
    if (sql_lock->table_count && lock_external(session, sql_lock->table,
 
249
    if (sql_lock->table_count && lock_external(session, sql_lock->getTable(),
246
250
                                               sql_lock->table_count))
247
251
    {
248
252
      /* Clear the lock type of all lock data to avoid reusage. */
251
255
    }
252
256
    session->set_proc_info("Table lock");
253
257
    /* Copy the lock data array. thr_multi_lock() reorders its contens. */
254
 
    memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
255
 
           sql_lock->lock_count * sizeof(*sql_lock->locks));
 
258
    memcpy(sql_lock->getLocks() + sql_lock->lock_count,
 
259
           sql_lock->getLocks(),
 
260
           sql_lock->lock_count * sizeof(*sql_lock->getLocks()));
256
261
    /* Lock on the copied half of the lock data array. */
257
 
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
 
262
    rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->getLocks() +
258
263
                                                     sql_lock->lock_count,
259
264
                                                     sql_lock->lock_count,
260
265
                                                     session->lock_id)];
261
266
    if (rc > 1)                                 /* a timeout or a deadlock */
262
267
    {
263
268
      if (sql_lock->table_count)
264
 
        unlock_external(session, sql_lock->table, sql_lock->table_count);
 
269
        unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
265
270
      reset_lock_data_and_free(&sql_lock);
266
271
      my_error(rc, MYF(0));
267
272
      break;
290
295
 
291
296
    /* going to retry, unlock all tables */
292
297
    if (sql_lock->lock_count)
293
 
        thr_multi_unlock(sql_lock->locks, sql_lock->lock_count);
 
298
        sql_lock->unlock(sql_lock->lock_count);
294
299
 
295
300
    if (sql_lock->table_count)
296
 
      unlock_external(session, sql_lock->table, sql_lock->table_count);
 
301
      unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
297
302
 
298
303
    /*
299
304
      If thr_multi_lock fails it resets lock type for tables, which
335
340
 
336
341
static int lock_external(Session *session, Table **tables, uint32_t count)
337
342
{
338
 
  register uint32_t i;
339
343
  int lock_type,error;
340
 
  for (i=1 ; i <= count ; i++, tables++)
 
344
  for (uint32_t i= 1 ; i <= count ; i++, tables++)
341
345
  {
342
346
    assert((*tables)->reginfo.lock_type >= TL_READ);
343
347
    lock_type=F_WRLCK;                          /* Lock exclusive */
348
352
 
349
353
    if ((error=(*tables)->cursor->ha_external_lock(session,lock_type)))
350
354
    {
351
 
      print_lock_error(error, (*tables)->cursor->engine->getName().c_str());
 
355
      print_lock_error(error, (*tables)->cursor->getEngine()->getName().c_str());
352
356
      while (--i)
353
357
      {
354
358
        tables--;
367
371
}
368
372
 
369
373
 
370
 
void mysql_unlock_tables(Session *session, DRIZZLE_LOCK *sql_lock)
 
374
void mysql_unlock_tables(Session *session, DrizzleLock *sql_lock)
371
375
{
372
376
  if (sql_lock->lock_count)
373
 
    thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
 
377
    sql_lock->unlock(sql_lock->lock_count);
374
378
  if (sql_lock->table_count)
375
 
    unlock_external(session,sql_lock->table,sql_lock->table_count);
376
 
  free((unsigned char*) sql_lock);
377
 
  return;
 
379
    unlock_external(session, sql_lock->getTable(), sql_lock->table_count);
 
380
  delete sql_lock;
378
381
}
379
382
 
380
383
/**
385
388
 
386
389
void mysql_unlock_some_tables(Session *session, Table **table, uint32_t count)
387
390
{
388
 
  DRIZZLE_LOCK *sql_lock;
 
391
  DrizzleLock *sql_lock;
389
392
  Table *write_lock_used;
390
393
  if ((sql_lock= get_lock_data(session, table, count, false,
391
394
                               &write_lock_used)))
397
400
  unlock all tables locked for read.
398
401
*/
399
402
 
400
 
void mysql_unlock_read_tables(Session *session, DRIZZLE_LOCK *sql_lock)
 
403
void mysql_unlock_read_tables(Session *session, DrizzleLock *sql_lock)
401
404
{
402
405
  uint32_t i,found;
403
406
 
404
407
  /* Move all write locks first */
405
 
  THR_LOCK_DATA **lock=sql_lock->locks;
 
408
  THR_LOCK_DATA **lock=sql_lock->getLocks();
406
409
  for (i=found=0 ; i < sql_lock->lock_count ; i++)
407
410
  {
408
 
    if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
 
411
    if (sql_lock->getLocks()[i]->type >= TL_WRITE_ALLOW_READ)
409
412
    {
410
 
      std::swap(*lock, sql_lock->locks[i]);
 
413
      std::swap(*lock, sql_lock->getLocks()[i]);
411
414
      lock++;
412
415
      found++;
413
416
    }
415
418
  /* unlock the read locked tables */
416
419
  if (i != found)
417
420
  {
418
 
    thr_multi_unlock(lock,i-found);
 
421
    sql_lock->unlock(i - found);
419
422
    sql_lock->lock_count= found;
420
423
  }
421
424
 
422
425
  /* Then do the same for the external locks */
423
426
  /* Move all write locked tables first */
424
 
  Table **table=sql_lock->table;
 
427
  Table **table= sql_lock->getTable();
425
428
  for (i=found=0 ; i < sql_lock->table_count ; i++)
426
429
  {
427
 
    assert(sql_lock->table[i]->lock_position == i);
428
 
    if ((uint32_t) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
 
430
    assert(sql_lock->getTable()[i]->lock_position == i);
 
431
    if ((uint32_t) sql_lock->getTable()[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
429
432
    {
430
 
      std::swap(*table, sql_lock->table[i]);
 
433
      std::swap(*table, sql_lock->getTable()[i]);
431
434
      table++;
432
435
      found++;
433
436
    }
439
442
    sql_lock->table_count=found;
440
443
  }
441
444
  /* Fix the lock positions in Table */
442
 
  table= sql_lock->table;
 
445
  table= sql_lock->getTable();
443
446
  found= 0;
444
447
  for (i= 0; i < sql_lock->table_count; i++)
445
448
  {
446
449
    Table *tbl= *table;
447
 
    tbl->lock_position= table - sql_lock->table;
 
450
    tbl->lock_position= table - sql_lock->getTable();
448
451
    tbl->lock_data_start= found;
449
452
    found+= tbl->lock_count;
450
453
    table++;
483
486
 
484
487
void mysql_lock_abort(Session *session, Table *table)
485
488
{
486
 
  DRIZZLE_LOCK *locked;
 
489
  DrizzleLock *locked;
487
490
  Table *write_lock_used;
488
491
 
489
492
  if ((locked= get_lock_data(session, &table, 1, false,
490
493
                             &write_lock_used)))
491
494
  {
492
495
    for (uint32_t x= 0; x < locked->lock_count; x++)
493
 
      thr_abort_locks(locked->locks[x]->lock);
494
 
    free((unsigned char*) locked);
 
496
      locked->getLocks()[x]->lock->abort_locks();
 
497
    delete locked;
495
498
  }
496
499
}
497
500
 
510
513
 
511
514
bool mysql_lock_abort_for_thread(Session *session, Table *table)
512
515
{
513
 
  DRIZZLE_LOCK *locked;
 
516
  DrizzleLock *locked;
514
517
  Table *write_lock_used;
515
518
  bool result= false;
516
519
 
517
520
  if ((locked= get_lock_data(session, &table, 1, false,
518
521
                             &write_lock_used)))
519
522
  {
520
 
    for (uint32_t i=0; i < locked->lock_count; i++)
 
523
    for (uint32_t i= 0; i < locked->lock_count; i++)
521
524
    {
522
 
      if (thr_abort_locks_for_thread(locked->locks[i]->lock,
523
 
                                     table->in_use->thread_id))
 
525
      if (locked->getLocks()[i]->lock->abort_locks_for_thread(table->in_use->thread_id))
524
526
        result= true;
525
527
    }
526
 
    free((unsigned char*) locked);
 
528
    delete locked;
527
529
  }
528
530
  return result;
529
531
}
530
532
 
531
533
/** Unlock a set of external. */
532
534
 
533
 
static int unlock_external(Session *session, Table **table,uint32_t count)
 
535
static int unlock_external(Session *session, Table **table, uint32_t count)
534
536
{
535
537
  int error,error_code;
536
538
 
543
545
      if ((error=(*table)->cursor->ha_external_lock(session, F_UNLCK)))
544
546
      {
545
547
        error_code=error;
546
 
        print_lock_error(error_code, (*table)->cursor->engine->getName().c_str());
 
548
        print_lock_error(error_code, (*table)->cursor->getEngine()->getName().c_str());
547
549
      }
548
550
    }
549
551
    table++;
563
565
  @param write_lock_used   Store pointer to last table with WRITE_ALLOW_WRITE
564
566
*/
565
567
 
566
 
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
 
568
static DrizzleLock *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
567
569
                                 bool should_lock, Table **write_lock_used)
568
570
{
569
 
  uint32_t i,tables,lock_count;
570
 
  DRIZZLE_LOCK *sql_lock;
 
571
  uint32_t lock_count;
 
572
  DrizzleLock *sql_lock;
571
573
  THR_LOCK_DATA **locks, **locks_buf, **locks_start;
572
574
  Table **to, **table_buf;
573
575
 
574
576
  *write_lock_used=0;
575
 
  for (i= tables= lock_count= 0 ; i < count ; i++)
 
577
  for (uint32_t i= lock_count= 0 ; i < count ; i++)
576
578
  {
577
579
    Table *t= table_ptr[i];
578
580
 
579
581
    if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
580
582
    {
581
 
      tables++;
582
583
      lock_count++;
583
584
    }
584
585
  }
589
590
    update the table values. So the second part of the array is copied
590
591
    from the first part immediately before calling thr_multi_lock().
591
592
  */
592
 
  if (!(sql_lock= (DRIZZLE_LOCK*)
593
 
        malloc(sizeof(*sql_lock) +
594
 
               sizeof(THR_LOCK_DATA*) * tables * 2 +
595
 
               sizeof(table_ptr) * lock_count)))
 
593
  sql_lock= new DrizzleLock(lock_count, lock_count*2);
 
594
 
 
595
  if (not sql_lock)
596
596
    return NULL;
597
 
  locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
598
 
  to= table_buf= sql_lock->table= (Table**) (locks + tables * 2);
599
 
  sql_lock->table_count= lock_count;
600
 
 
601
 
  for (i=0 ; i < count ; i++)
 
597
 
 
598
  locks= locks_buf= sql_lock->getLocks();
 
599
  to= table_buf= sql_lock->getTable();
 
600
 
 
601
  for (uint32_t i= 0; i < count ; i++)
602
602
  {
603
603
    Table *table;
604
604
    enum thr_lock_type lock_type;
614
614
      *write_lock_used=table;
615
615
      if (table->db_stat & HA_READ_ONLY)
616
616
      {
617
 
        my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
 
617
        my_error(ER_OPEN_AS_READONLY, MYF(0), table->getAlias());
618
618
        /* Clear the lock type of the lock data that are stored already. */
619
 
        sql_lock->lock_count= locks - sql_lock->locks;
 
619
        sql_lock->lock_count= locks - sql_lock->getLocks();
620
620
        reset_lock_data_and_free(&sql_lock);
621
621
        return NULL;
622
622
      }
680
680
    > 0  table locked, but someone is using it
681
681
*/
682
682
 
683
 
int lock_table_name(Session *session, TableList *table_list, bool check_in_use)
 
683
static int lock_table_name(Session *session, TableList *table_list, bool check_in_use)
684
684
{
685
 
  Table *table;
686
 
  char  key[MAX_DBKEY_LENGTH];
687
 
  char *db= table_list->db;
688
 
  uint32_t  key_length;
689
685
  bool  found_locked_table= false;
690
 
  HASH_SEARCH_STATE state;
691
 
 
692
 
  key_length= table_list->create_table_def_key(key);
 
686
  TableIdentifier identifier(table_list->db, table_list->table_name);
 
687
  const TableIdentifier::Key &key(identifier.getKey());
693
688
 
694
689
  if (check_in_use)
695
690
  {
696
691
    /* Only insert the table if we haven't insert it already */
697
 
    for (table=(Table*) hash_first(&open_cache, (unsigned char*)key,
698
 
                                   key_length, &state);
699
 
         table ;
700
 
         table = (Table*) hash_next(&open_cache,(unsigned char*) key,
701
 
                                    key_length, &state))
 
692
    TableOpenCacheRange ppp;
 
693
 
 
694
    ppp= get_open_cache().equal_range(key);
 
695
 
 
696
    for (TableOpenCache::const_iterator iter= ppp.first;
 
697
         iter != ppp.second; ++iter)
702
698
    {
 
699
      Table *table= (*iter).second;
703
700
      if (table->reginfo.lock_type < TL_WRITE)
704
701
      {
705
702
        if (table->in_use == session)
709
706
 
710
707
      if (table->in_use == session)
711
708
      {
712
 
        table->s->version= 0;                  // Ensure no one can use this
713
 
        table->locked_by_name= 1;
 
709
        table->getMutableShare()->resetVersion();                  // Ensure no one can use this
 
710
        table->locked_by_name= true;
714
711
        return 0;
715
712
      }
716
713
    }
717
714
  }
718
715
 
719
 
  if (!(table= session->table_cache_insert_placeholder(key, key_length)))
 
716
  Table *table;
 
717
  if (!(table= session->table_cache_insert_placeholder(table_list->db, table_list->table_name)))
 
718
  {
720
719
    return -1;
 
720
  }
721
721
 
722
 
  table_list->table=table;
 
722
  table_list->table= table;
723
723
 
724
724
  /* Return 1 if table is in use */
725
 
  return(test(remove_table_from_cache(session, db, table_list->table_name,
726
 
             check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
 
725
  return(test(remove_table_from_cache(session, identifier,
 
726
                                      check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
727
727
}
728
728
 
729
729
 
731
731
{
732
732
  if (table_list->table)
733
733
  {
734
 
    hash_delete(&open_cache, (unsigned char*) table_list->table);
 
734
    remove_table(dynamic_cast<table::Concurrent *>(table_list->table));
735
735
    broadcast_refresh();
736
736
  }
737
737
}
744
744
    Table *table= table_list->table;
745
745
    if (table)
746
746
    {
747
 
      Table *save_next= table->next;
 
747
      Table *save_next= table->getNext();
748
748
      bool result;
749
 
      table->next= 0;
 
749
      table->setNext(NULL);
750
750
      result= table_is_used(table_list->table, 0);
751
 
      table->next= save_next;
 
751
      table->setNext(save_next);
752
752
      if (result)
753
753
        return 1;
754
754
    }
757
757
}
758
758
 
759
759
 
760
 
bool wait_for_locked_table_names(Session *session, TableList *table_list)
 
760
static bool wait_for_locked_table_names(Session *session, TableList *table_list)
761
761
{
762
762
  bool result= false;
763
763
 
764
 
  safe_mutex_assert_owner(&LOCK_open);
 
764
#if 0
 
765
  assert(ownership of LOCK_open);
 
766
#endif
765
767
 
766
768
  while (locked_named_table(table_list))
767
769
  {
770
772
      result=1;
771
773
      break;
772
774
    }
773
 
    session->wait_for_condition(&LOCK_open, &COND_refresh);
774
 
    pthread_mutex_lock(&LOCK_open); /* Wait for a table to unlock and then lock it */
 
775
    session->wait_for_condition(LOCK_open, COND_refresh);
 
776
    LOCK_open.lock(); /* Wait for a table to unlock and then lock it */
775
777
  }
776
778
  return result;
777
779
}
791
793
    1   Fatal error (end of memory ?)
792
794
*/
793
795
 
794
 
bool lock_table_names(Session *session, TableList *table_list)
 
796
static bool lock_table_names(Session *session, TableList *table_list)
795
797
{
796
798
  bool got_all_locks=1;
797
799
  TableList *lock_table;
799
801
  for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
800
802
  {
801
803
    int got_lock;
802
 
    if ((got_lock= lock_table_name(session,lock_table, true)) < 0)
 
804
    if ((got_lock= lock_table_name(session, lock_table, true)) < 0)
803
805
      goto end;                                 // Fatal error
804
806
    if (got_lock)
805
807
      got_all_locks=0;                          // Someone is using table
1002
1004
  if (!session->global_read_lock)
1003
1005
  {
1004
1006
    const char *old_message;
1005
 
    (void) pthread_mutex_lock(&LOCK_global_read_lock);
1006
 
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1007
 
                                "Waiting to get readlock");
 
1007
    LOCK_global_read_lock.lock();
 
1008
    old_message=session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1009
                                    "Waiting to get readlock");
1008
1010
 
1009
1011
    waiting_for_read_lock++;
 
1012
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
1010
1013
    while (protect_against_global_read_lock && !session->killed)
1011
 
      pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1014
      COND_global_read_lock.wait(scopedLock);
1012
1015
    waiting_for_read_lock--;
 
1016
    scopedLock.release();
1013
1017
    if (session->killed)
1014
1018
    {
1015
1019
      session->exit_cond(old_message);
1035
1039
{
1036
1040
  uint32_t tmp;
1037
1041
 
1038
 
  pthread_mutex_lock(&LOCK_global_read_lock);
1039
 
  tmp= --global_read_lock;
1040
 
  if (session->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1041
 
    --global_read_lock_blocks_commit;
1042
 
  pthread_mutex_unlock(&LOCK_global_read_lock);
 
1042
  {
 
1043
    boost_unique_lock_t scopedLock(LOCK_global_read_lock);
 
1044
    tmp= --global_read_lock;
 
1045
    if (session->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
 
1046
      --global_read_lock_blocks_commit;
 
1047
  }
1043
1048
  /* Send the signal outside the mutex to avoid a context switch */
1044
1049
  if (!tmp)
1045
1050
  {
1046
 
    pthread_cond_broadcast(&COND_global_read_lock);
 
1051
    COND_global_read_lock.notify_all();
1047
1052
  }
1048
1053
  session->global_read_lock= 0;
1049
1054
}
1066
1071
    threads could not close their tables. This would make a pretty
1067
1072
    deadlock.
1068
1073
  */
1069
 
  safe_mutex_assert_not_owner(&LOCK_open);
 
1074
  safe_mutex_assert_not_owner(LOCK_open.native_handle());
1070
1075
 
1071
 
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
 
1076
  LOCK_global_read_lock.lock();
1072
1077
  if ((need_exit_cond= must_wait(is_not_commit)))
1073
1078
  {
1074
1079
    if (session->global_read_lock)              // This thread had the read locks
1076
1081
      if (is_not_commit)
1077
1082
        my_message(ER_CANT_UPDATE_WITH_READLOCK,
1078
1083
                   ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
1079
 
      (void) pthread_mutex_unlock(&LOCK_global_read_lock);
 
1084
      LOCK_global_read_lock.unlock();
1080
1085
      /*
1081
1086
        We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
1082
1087
        This allowance is needed to not break existing versions of innobackup
1084
1089
      */
1085
1090
      return is_not_commit;
1086
1091
    }
1087
 
    old_message=session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1088
 
                                "Waiting for release of readlock");
 
1092
    old_message=session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1093
                                    "Waiting for release of readlock");
1089
1094
    while (must_wait(is_not_commit) && ! session->killed &&
1090
1095
           (!abort_on_refresh || session->version == refresh_version))
1091
1096
    {
1092
 
      (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1097
      boost_unique_lock_t scoped(LOCK_global_read_lock, boost::adopt_lock_t());
 
1098
      COND_global_read_lock.wait(scoped);
 
1099
      scoped.release();
1093
1100
    }
1094
1101
    if (session->killed)
1095
1102
      result=1;
1103
1110
  if (unlikely(need_exit_cond))
1104
1111
    session->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1105
1112
  else
1106
 
    pthread_mutex_unlock(&LOCK_global_read_lock);
 
1113
    LOCK_global_read_lock.unlock();
1107
1114
  return result;
1108
1115
}
1109
1116
 
1113
1120
  bool tmp;
1114
1121
  if (unlikely(session->global_read_lock))
1115
1122
    return;
1116
 
  (void) pthread_mutex_lock(&LOCK_global_read_lock);
 
1123
  LOCK_global_read_lock.lock();
1117
1124
  tmp= (!--protect_against_global_read_lock &&
1118
1125
        (waiting_for_read_lock || global_read_lock_blocks_commit));
1119
 
  (void) pthread_mutex_unlock(&LOCK_global_read_lock);
 
1126
  LOCK_global_read_lock.unlock();
1120
1127
  if (tmp)
1121
 
    pthread_cond_broadcast(&COND_global_read_lock);
 
1128
    COND_global_read_lock.notify_all();
1122
1129
  return;
1123
1130
}
1124
1131
 
1133
1140
  */
1134
1141
  if (session->global_read_lock != GOT_GLOBAL_READ_LOCK)
1135
1142
    return false;
1136
 
  pthread_mutex_lock(&LOCK_global_read_lock);
 
1143
  LOCK_global_read_lock.lock();
1137
1144
  /* increment this BEFORE waiting on cond (otherwise race cond) */
1138
1145
  global_read_lock_blocks_commit++;
1139
 
  old_message= session->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1140
 
                               "Waiting for all running commits to finish");
 
1146
  old_message= session->enter_cond(COND_global_read_lock, LOCK_global_read_lock,
 
1147
                                   "Waiting for all running commits to finish");
1141
1148
  while (protect_against_global_read_lock && !session->killed)
1142
 
    pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
 
1149
  {
 
1150
    boost_unique_lock_t scopedLock(LOCK_global_read_lock, boost::adopt_lock_t());
 
1151
    COND_global_read_lock.wait(scopedLock);
 
1152
    scopedLock.release();
 
1153
  }
1143
1154
  if ((error= test(session->killed)))
1144
1155
    global_read_lock_blocks_commit--; // undo what we did
1145
1156
  else
1170
1181
 
1171
1182
void broadcast_refresh(void)
1172
1183
{
1173
 
  pthread_cond_broadcast(&COND_refresh);
1174
 
  pthread_cond_broadcast(&COND_global_read_lock);
 
1184
  COND_refresh.notify_all();
 
1185
  COND_global_read_lock.notify_all();
1175
1186
}
1176
1187
 
1177
1188