+static struct pending_request *
+check_trigger(struct timespec *ts)
+{
+ struct pending_request *next, *cur, *trigger = NULL;
+
+ TAILQ_FOREACH_SAFE(cur, &pending_requests.requests, next, next) {
+ enum async_action action;
+ if (cur->type != REQUEST_TYPE_ASYNC)
+ continue;
+
+ action = process_async_request(cur, ts);
+ if (action == ACTION_FREE) {
+ TAILQ_REMOVE(&pending_requests.requests, cur, next);
+ free(cur);
+ } else if (action == ACTION_TRIGGER) {
+ TAILQ_REMOVE(&pending_requests.requests, cur, next);
+ trigger = cur;
+ break;
+ }
+ }
+ return trigger;
+}
+
+static void
+wait_for_async_messages(void)
+{
+ struct pending_request *sr;
+ struct timespec timeout;
+ bool timedwait = false;
+ bool nowait = false;
+ int ret;
+
+ /* scan through the list and see if there are any timeouts that
+ * are earlier than our current timeout.
+ */
+ TAILQ_FOREACH(sr, &pending_requests.requests, next) {
+ if (sr->type != REQUEST_TYPE_ASYNC)
+ continue;
+ if (!timedwait || timespec_cmp(&sr->async.param->end,
+ &timeout) < 0) {
+ memcpy(&timeout, &sr->async.param->end,
+ sizeof(timeout));
+ timedwait = true;
+ }
+
+ /* sometimes, we don't even wait */
+ if (sr->reply_received) {
+ nowait = true;
+ break;
+ }
+ }
+
+ if (nowait)
+ return;
+
+ do {
+ ret = timedwait ?
+ pthread_cond_timedwait(
+ &pending_requests.async_cond,
+ &pending_requests.lock,
+ &timeout) :
+ pthread_cond_wait(
+ &pending_requests.async_cond,
+ &pending_requests.lock);
+ } while (ret != 0 && ret != ETIMEDOUT);
+
+ /* we've been woken up or timed out */
+}
+