From: Jon Olav Hauglid Date: January 14 2011 2:06pm Subject: bzr commit into mysql-5.5 branch (jon.hauglid:3244) Bug#43152 List-Archive: http://lists.mysql.com/commits/128772 X-Bug: 43152 Message-Id: <201101141408.p0EC4QZ6002203@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7463866092955492222==" --===============7463866092955492222== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/x/mysql-5.5-bug43152/ based on revid:georgi.kodinov@stripped 3244 Jon Olav Hauglid 2011-01-14 Bug #43152 Assertion `bitmap_is_set_all(&table->s->all_set)' failed in handler::ha_reset This assertion could be triggered if two connections simultaneously executed two bitmap test functions on the same bitmap. Even if these functions have read-only schematics and have const bitmaps as parameters, several of them modified the internal state of the bitmap. With interleaved execution of two such functions it was possible for one function to modify the state of the same bitmap that the other function had just modified. This lead to an inconsistent state and could trigger the assert. Internally the bitmap uses 32 bit words for storage. Since bitmaps can contain any number of bits, the last word in the bitmap may not be fully used. A 32 bit mask is maintained where a bit is set if the corresponding bit in the last bitmap word is unused. The problem was that several test functions applies this mask to the last word. Some used bitwise AND and some used bitwise OR. This meant that if a function first used bitwise AND and another function then used bitwise OR before the first function tested the result, the result would be invalid. This patch fixes the problem by changing the implementation of 8 bitmap functions that modified the bitmap state even if the bitmap was declared const. These functions now preserves the internal state of the bitmap. This makes it possible for two connections to concurrently execute two of these functions on the same bitmap without issues. The patch also reactivates the built-in test of my_bitmap. No test case added as this would require adding several sync points to the bitmap functions. The patch has been tested with a non-deterministic test case posted on the bug report. modified: .bzrignore include/my_bit.h mysys/CMakeLists.txt mysys/my_bitmap.c === modified file '.bzrignore' --- a/.bzrignore 2010-12-17 11:11:34 +0000 +++ b/.bzrignore 2011-01-14 14:06:36 +0000 @@ -3115,4 +3115,5 @@ libmysqld/mysqlserver_depends.c libmysqld/examples/mysql_embedded sql/.empty mysys/thr_lock +mysys/my_bitmap VERSION.dep === modified file 'include/my_bit.h' --- a/include/my_bit.h 2010-07-23 20:18:36 +0000 +++ b/include/my_bit.h 2011-01-14 14:06:36 +0000 @@ -49,6 +49,13 @@ static inline uint my_count_bits_ushort( return _my_bits_nbits[v]; } +static inline uint my_count_bits_uint32(uint32 v) +{ + return (uint) (uchar) (_my_bits_nbits[(uchar) v] + + _my_bits_nbits[(uchar) (v >> 8)] + + _my_bits_nbits[(uchar) (v >> 16)] + + _my_bits_nbits[(uchar) (v >> 24)]); +} /* Next highest power of two === modified file 'mysys/CMakeLists.txt' --- a/mysys/CMakeLists.txt 2010-08-12 15:19:57 +0000 +++ b/mysys/CMakeLists.txt 2011-01-14 14:06:36 +0000 @@ -77,3 +77,7 @@ DTRACE_INSTRUMENT(mysys) ADD_EXECUTABLE(thr_lock thr_lock.c) TARGET_LINK_LIBRARIES(thr_lock mysys) SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN") + +ADD_EXECUTABLE(my_bitmap my_bitmap.c) +TARGET_LINK_LIBRARIES(my_bitmap mysys) +SET_TARGET_PROPERTIES(my_bitmap PROPERTIES COMPILE_FLAGS "-DMAIN") === modified file 'mysys/my_bitmap.c' --- a/mysys/my_bitmap.c 2011-01-11 09:07:37 +0000 +++ b/mysys/my_bitmap.c 2011-01-14 14:06:36 +0000 @@ -259,39 +259,42 @@ void bitmap_set_prefix(MY_BITMAP *map, u my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size & 0x7, res; - uchar *m= (uchar*)map->bitmap; - uchar *end_prefix= m+prefix_size/8; - uchar *end; - DBUG_ASSERT(m && prefix_size <= map->n_bits); - end= m+no_bytes_in_map(map); - - while (m < end_prefix) - if (*m++ != 0xff) - return 0; - - *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/ - res= 0; - if (prefix_bits && *m++ != (1 << prefix_bits)-1) - goto ret; - - while (m < end) - if (*m++ != 0) - goto ret; - res= 1; -ret: - return res; + my_bitmap_map prefix_bits= prefix_size & 0x7FFF; + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end_prefix= data_ptr+prefix_size/32; + DBUG_ASSERT(data_ptr && prefix_size <= map->n_bits); + + for (; data_ptr < end_prefix; data_ptr++) + if (*data_ptr != 0xFFFFFFFF) + return FALSE; + + if (prefix_bits) + { + my_bitmap_map word= *data_ptr; + if (data_ptr++ == map->last_word_ptr) + word &= ~map->last_word_mask; + if (word != (my_bitmap_map)((1 << prefix_bits)-1)) + return FALSE; + } + + for (; data_ptr < map->last_word_ptr; data_ptr++) + if (*data_ptr != 0) + return FALSE; + if (data_ptr == map->last_word_ptr && + (*map->last_word_ptr & ~map->last_word_mask) != 0) + return FALSE; + return TRUE; } my_bool bitmap_is_set_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; - my_bitmap_map *end= map->last_word_ptr; - *map->last_word_ptr |= map->last_word_mask; - for (; data_ptr <= end; data_ptr++) + for (; data_ptr < map->last_word_ptr; data_ptr++) if (*data_ptr != 0xFFFFFFFF) return FALSE; + if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF) + return FALSE; return TRUE; } @@ -313,40 +316,44 @@ my_bool bitmap_is_clear_all(const MY_BIT my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap; DBUG_ASSERT(map1->bitmap && map2->bitmap && map1->n_bits==map2->n_bits); - end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) + while (m1 < map1->last_word_ptr) { if ((*m1++) & ~(*m2++)) - return 0; + return FALSE; } - return 1; + + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + ~(*map2->last_word_ptr & ~map2->last_word_mask)) + return FALSE; + + return TRUE; } /* True if bitmaps has any common bits */ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap; DBUG_ASSERT(map1->bitmap && map2->bitmap && map1->n_bits==map2->n_bits); - end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) + while (m1 < map1->last_word_ptr) { if ((*m1++) & (*m2++)) - return 1; + return TRUE; } - return 0; + + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + (*map2->last_word_ptr & ~map2->last_word_mask)) + return TRUE; + + return FALSE; } @@ -358,9 +365,13 @@ void bitmap_intersect(MY_BITMAP *map, co DBUG_ASSERT(map->bitmap && map2->bitmap); end= to+min(len,len2); - *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ while (to < end) - *to++ &= *from++; + { + if (from == map2->last_word_ptr) + *to++ &= (*from & ~map2->last_word_mask); /*Clear last bits in map2*/ + else + *to++ &= *from++; + } if (len2 < len) { @@ -451,15 +462,15 @@ void bitmap_invert(MY_BITMAP *map) uint bitmap_bits_set(const MY_BITMAP *map) -{ - uchar *m= (uchar*)map->bitmap; - uchar *end= m + no_bytes_in_map(map); +{ + my_bitmap_map *data_ptr= map->bitmap; uint res= 0; DBUG_ASSERT(map->bitmap); - *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/ - while (m < end) - res+= my_count_bits_ushort(*m++); + while (data_ptr < map->last_word_ptr) + res+= my_count_bits_uint32(*data_ptr++); + /*Reset last bits to zero*/ + res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask); return res; } @@ -479,26 +490,29 @@ void bitmap_copy(MY_BITMAP *map, const M uint bitmap_get_first_set(const MY_BITMAP *map) { uchar *byte_ptr; - uint i,j,k; - my_bitmap_map *data_ptr, *end= map->last_word_ptr; + uint word_pos, byte_pos, bit_pos; + my_bitmap_map *data_ptr, last_word; DBUG_ASSERT(map->bitmap); data_ptr= map->bitmap; - *map->last_word_ptr &= ~map->last_word_mask; + last_word= *map->last_word_ptr & ~map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) + for (word_pos=0; data_ptr <= map->last_word_ptr; data_ptr++, word_pos++) { if (*data_ptr) { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) + if (data_ptr == map->last_word_ptr) + byte_ptr= (uchar*)&last_word; + else + byte_ptr= (uchar*)data_ptr; + for (byte_pos=0; ; byte_pos++, byte_ptr++) { if (*byte_ptr) { - for (k=0; ; k++) + for (bit_pos=0; ; bit_pos++) { - if (*byte_ptr & (1 << k)) - return (i*32) + (j*8) + k; + if (*byte_ptr & (1 << bit_pos)) + return (word_pos*32) + (byte_pos*8) + bit_pos; } } } @@ -511,26 +525,29 @@ uint bitmap_get_first_set(const MY_BITMA uint bitmap_get_first(const MY_BITMAP *map) { uchar *byte_ptr; - uint i,j,k; - my_bitmap_map *data_ptr, *end= map->last_word_ptr; + uint word_pos, byte_pos, bit_pos; + my_bitmap_map *data_ptr, last_word; DBUG_ASSERT(map->bitmap); data_ptr= map->bitmap; - *map->last_word_ptr|= map->last_word_mask; + last_word= *map->last_word_ptr | map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) + for (word_pos=0; data_ptr <= map->last_word_ptr; data_ptr++, word_pos++) { if (*data_ptr != 0xFFFFFFFF) { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) + if (data_ptr == map->last_word_ptr) + byte_ptr= (uchar*)&last_word; + else + byte_ptr= (uchar*)data_ptr; + for (byte_pos=0; ; byte_pos++, byte_ptr++) { if (*byte_ptr != 0xFF) { - for (k=0; ; k++) + for (bit_pos=0; ; bit_pos++) { - if (!(*byte_ptr & (1 << k))) - return (i*32) + (j*8) + k; + if (!(*byte_ptr & (1 << bit_pos))) + return (word_pos*32) + (byte_pos*8) + bit_pos; } } } @@ -565,7 +582,7 @@ uint get_rand_bit(uint bitsize) return (rand() % bitsize); } -bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) +my_bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -588,7 +605,7 @@ error2: return TRUE; } -bool test_flip_bit(MY_BITMAP *map, uint bitsize) +my_bool test_flip_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -611,13 +628,13 @@ error2: return TRUE; } -bool test_operators(MY_BITMAP *map __attribute__((unused)), +my_bool test_operators(MY_BITMAP *map __attribute__((unused)), uint bitsize __attribute__((unused))) { return FALSE; } -bool test_get_all_bits(MY_BITMAP *map, uint bitsize) +my_bool test_get_all_bits(MY_BITMAP *map, uint bitsize) { uint i; bitmap_set_all(map); @@ -659,7 +676,7 @@ error6: return TRUE; } -bool test_compare_operators(MY_BITMAP *map, uint bitsize) +my_bool test_compare_operators(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit1, test_bit2, test_bit3,test_bit4; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -765,7 +782,7 @@ error5: return TRUE; } -bool test_count_bits_set(MY_BITMAP *map, uint bitsize) +my_bool test_count_bits_set(MY_BITMAP *map, uint bitsize) { uint i, bit_count=0, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -791,7 +808,7 @@ error2: return TRUE; } -bool test_get_first_bit(MY_BITMAP *map, uint bitsize) +my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -816,7 +833,7 @@ error2: return TRUE; } -bool test_get_next_bit(MY_BITMAP *map, uint bitsize) +my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -835,7 +852,7 @@ error1: return TRUE; } -bool test_prefix(MY_BITMAP *map, uint bitsize) +my_bool test_prefix(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -870,7 +887,7 @@ error3: } -bool do_test(uint bitsize) +my_bool do_test(uint bitsize) { MY_BITMAP map; my_bitmap_map buf[1024]; --===============7463866092955492222== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jon.hauglid@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jon.hauglid@stripped # target_branch: file:///export/home/x/mysql-5.5-bug43152/ # testament_sha1: f02f9512e9682d8dc522eb6d42b1b9a8150fc5a2 # timestamp: 2011-01-14 15:06:39 +0100 # base_revision_id: georgi.kodinov@stripped\ # hjhfb8de7zxnkqdu # # Begin bundle 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 NNJ39yVPIUF7GQPtF3JFOFCQiideOw== --===============7463866092955492222==--