called by a *waiter* (thd) to start waiting It's supposed to be a drop-in replacement for pthread_cond_timedwait(), and it takes mutex as an argument. @return one of WT_TIMEOUT, WT_DEADLOCK, WT_OK */
| 1137 | @return one of WT_TIMEOUT, WT_DEADLOCK, WT_OK |
| 1138 | */ |
| 1139 | int wt_thd_cond_timedwait(WT_THD *thd, mysql_mutex_t *mutex) |
| 1140 | { |
| 1141 | int ret= WT_TIMEOUT; |
| 1142 | struct timespec timeout; |
| 1143 | ulonglong before, after, starttime; |
| 1144 | WT_RESOURCE *rc= thd->waiting_for; |
| 1145 | DBUG_ENTER("wt_thd_cond_timedwait"); |
| 1146 | DBUG_PRINT("wt", ("enter: thd=%s, rc=%p", thd->name, rc)); |
| 1147 | |
| 1148 | #ifndef DBUG_OFF |
| 1149 | if (rc->cond_mutex) |
| 1150 | DBUG_ASSERT(rc->cond_mutex == mutex); |
| 1151 | else |
| 1152 | rc->cond_mutex= mutex; |
| 1153 | mysql_mutex_assert_owner(mutex); |
| 1154 | #endif |
| 1155 | |
| 1156 | before= starttime= my_getsystime(); |
| 1157 | |
| 1158 | #ifdef __WIN__ |
| 1159 | /* |
| 1160 | only for the sake of Windows we distinguish between |
| 1161 | 'before' and 'starttime': |
| 1162 | |
| 1163 | my_getsystime() returns high-resolution value, that cannot be used for |
| 1164 | waiting (it doesn't follow system clock changes), but is good for time |
| 1165 | intervals. |
| 1166 | |
| 1167 | GetSystemTimeAsFileTime() follows system clock, but is low-resolution |
| 1168 | and will result in lousy intervals. |
| 1169 | */ |
| 1170 | GetSystemTimeAsFileTime((PFILETIME)&starttime); |
| 1171 | #endif |
| 1172 | |
| 1173 | rc_wrlock(rc); |
| 1174 | if (rc->owners.elements == 0) |
| 1175 | ret= WT_OK; |
| 1176 | rc_unlock(rc); |
| 1177 | |
| 1178 | set_timespec_time_nsec(timeout, starttime, (*thd->timeout_short)*1000ULL); |
| 1179 | if (ret == WT_TIMEOUT && !thd->killed) |
| 1180 | ret= mysql_cond_timedwait(&rc->cond, mutex, &timeout); |
| 1181 | if (ret == WT_TIMEOUT && !thd->killed) |
| 1182 | { |
| 1183 | int r= deadlock(thd, thd, 0, *thd->deadlock_search_depth_long); |
| 1184 | if (r == WT_FREE_TO_GO) |
| 1185 | ret= WT_OK; |
| 1186 | else if (r != WT_OK) |
| 1187 | ret= WT_DEADLOCK; |
| 1188 | else if (*thd->timeout_long > *thd->timeout_short) |
| 1189 | { |
| 1190 | set_timespec_time_nsec(timeout, starttime, (*thd->timeout_long)*1000ULL); |
| 1191 | if (!thd->killed) |
| 1192 | ret= mysql_cond_timedwait(&rc->cond, mutex, &timeout); |
| 1193 | } |
| 1194 | } |
| 1195 | after= my_getsystime(); |
| 1196 | if (stop_waiting(thd) == WT_DEADLOCK) /* if we're killed */ |
nothing calls this directly
no test coverage detected