| 1108 | */ |
| 1109 | |
| 1110 | static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, |
| 1111 | my_bool at_end) |
| 1112 | { |
| 1113 | BLOCK_LINK *ins; |
| 1114 | BLOCK_LINK **pins; |
| 1115 | |
| 1116 | DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE)); |
| 1117 | DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ |
| 1118 | DBUG_ASSERT(!block->requests); |
| 1119 | DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); |
| 1120 | DBUG_ASSERT(!block->next_used); |
| 1121 | DBUG_ASSERT(!block->prev_used); |
| 1122 | |
| 1123 | if (!hot && keycache->waiting_for_block.last_thread) |
| 1124 | { |
| 1125 | /* Signal that in the LRU warm sub-chain an available block has appeared */ |
| 1126 | struct st_my_thread_var *last_thread= |
| 1127 | keycache->waiting_for_block.last_thread; |
| 1128 | struct st_my_thread_var *first_thread= last_thread->next; |
| 1129 | struct st_my_thread_var *next_thread= first_thread; |
| 1130 | HASH_LINK *hash_link= (HASH_LINK *) first_thread->opt_info; |
| 1131 | struct st_my_thread_var *thread; |
| 1132 | do |
| 1133 | { |
| 1134 | thread= next_thread; |
| 1135 | next_thread= thread->next; |
| 1136 | /* |
| 1137 | We notify about the event all threads that ask |
| 1138 | for the same page as the first thread in the queue |
| 1139 | */ |
| 1140 | if ((HASH_LINK *) thread->opt_info == hash_link) |
| 1141 | { |
| 1142 | KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); |
| 1143 | keycache_pthread_cond_signal(&thread->suspend); |
| 1144 | unlink_from_queue(&keycache->waiting_for_block, thread); |
| 1145 | block->requests++; |
| 1146 | } |
| 1147 | } |
| 1148 | while (thread != last_thread); |
| 1149 | hash_link->block= block; |
| 1150 | /* |
| 1151 | NOTE: We assigned the block to the hash_link and signalled the |
| 1152 | requesting thread(s). But it is possible that other threads runs |
| 1153 | first. These threads see the hash_link assigned to a block which |
| 1154 | is assigned to another hash_link and not marked BLOCK_IN_SWITCH. |
| 1155 | This can be a problem for functions that do not select the block |
| 1156 | via its hash_link: flush and free. They do only see a block which |
| 1157 | is in a "normal" state and don't know that it will be evicted soon. |
| 1158 | |
| 1159 | We cannot set BLOCK_IN_SWITCH here because only one of the |
| 1160 | requesting threads must handle the eviction. All others must wait |
| 1161 | for it to complete. If we set the flag here, the threads would not |
| 1162 | know who is in charge of the eviction. Without the flag, the first |
| 1163 | thread takes the stick and sets the flag. |
| 1164 | |
| 1165 | But we need to note in the block that is has been selected for |
| 1166 | eviction. It must not be freed. The evicting thread will not |
| 1167 | expect the block in the free list. Before freeing we could also |
no test coverage detected