process-list.h process-list.c \
qdevice-net-heuristics.c qdevice-net-heuristics.h \
qdevice-heuristics-result-notifier.c qdevice-heuristics-result-notifier.h \
- log.c log.h
+ log.c log.h pr-poll-loop.c pr-poll-loop.h \
+ qdevice-pr-poll-loop-cb.c qdevice-pr-poll-loop-cb.h \
+ qdevice-pr-poll-loop.c qdevice-pr-poll-loop.h
corosync_qdevice_tool_SOURCES = corosync-qdevice-tool.c unix-socket.c unix-socket.h dynar.c dynar.h \
dynar-str.c dynar-str.h utils.c utils.h
#include "qdevice-ipc.h"
#include "qdevice-log.h"
#include "qdevice-model.h"
+#include "qdevice-pr-poll-loop.h"
+#include "qdevice-pr-poll-loop-cb.h"
#include "qdevice-votequorum.h"
#include "utils.h"
return (EXIT_FAILURE);
}
+ log(LOG_DEBUG, "Registering main poll loop callbacks");
+ if (qdevice_pr_poll_loop_cb_register(&instance) != 0) {
+ return (EXIT_FAILURE);
+ }
+
log(LOG_DEBUG, "Waiting for ring id");
if (qdevice_votequorum_wait_for_ring_id(&instance) != 0) {
return (EXIT_FAILURE);
}
log(LOG_DEBUG, "Waiting for initial heuristics exec result");
- if (qdevice_instance_wait_for_initial_heuristics_exec_result(&instance) != 0) {
+ if (qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(&instance) != 0) {
return (EXIT_FAILURE);
}
#include "qdevice-config.h"
#include "qdevice-instance.h"
#include "qdevice-heuristics-exec-list.h"
-/*TODO Remove this 3 line includes when porting on pr-poll-loop */
-#include "qdevice-heuristics.h"
-#include "qdevice-heuristics-cmd.h"
-#include "qdevice-votequorum.h"
#include "qdevice-model.h"
#include "utils.h"
instance->vq_last_poll = ((time_t) -1);
instance->advanced_settings = advanced_settings;
+ pr_poll_loop_init(&instance->main_poll_loop);
return (0);
}
{
node_list_free(&instance->config_node_list);
+ pr_poll_loop_destroy(&instance->main_poll_loop);
return (0);
}
return (0);
}
-
-#define QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS 5
-
-int
-qdevice_instance_wait_for_initial_heuristics_exec_result(struct qdevice_instance *instance)
-{
- struct pollfd pfds[QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS];
- int no_pfds;
- int poll_res;
- int timeout;
- int i;
- int case_processed;
- int res;
-
- while (!instance->vq_node_list_initial_heuristics_finished) {
- no_pfds = 0;
-
- assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
- pfds[no_pfds].fd = instance->heuristics_instance.pipe_log_recv;
- pfds[no_pfds].events = POLLIN;
- pfds[no_pfds].revents = 0;
- no_pfds++;
-
- assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
- pfds[no_pfds].fd = instance->heuristics_instance.pipe_cmd_recv;
- pfds[no_pfds].events = POLLIN;
- pfds[no_pfds].revents = 0;
- no_pfds++;
-
- assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
- pfds[no_pfds].fd = instance->votequorum_poll_fd;
- pfds[no_pfds].events = POLLIN;
- pfds[no_pfds].revents = 0;
- no_pfds++;
-
- if (!send_buffer_list_empty(&instance->heuristics_instance.cmd_out_buffer_list)) {
- assert(no_pfds < QDEVICE_HEURISTICS_WAIT_FOR_INITIAL_EXEC_RESULT_MAX_PFDS);
- pfds[no_pfds].fd = instance->heuristics_instance.pipe_cmd_send;
- pfds[no_pfds].events = POLLOUT;
- pfds[no_pfds].revents = 0;
- no_pfds++;
- }
-
- /*
- * We know this is never larger than QDEVICE_DEFAULT_HEURISTICS_MAX_TIMEOUT * 2
- */
- timeout = (int)instance->heuristics_instance.sync_timeout * 2;
-
- poll_res = poll(pfds, no_pfds, timeout);
- if (poll_res > 0) {
- for (i = 0; i < no_pfds; i++) {
- if (pfds[i].revents & POLLIN) {
- case_processed = 0;
- switch (i) {
- case 0:
- case_processed = 1;
-
- res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
- if (res == -1) {
- return (-1);
- }
- break;
- case 1:
- case_processed = 1;
- res = qdevice_heuristics_cmd_read_from_pipe(&instance->heuristics_instance);
- if (res == -1) {
- return (-1);
- }
- break;
- case 2:
- case_processed = 1;
- res = qdevice_votequorum_dispatch(instance);
- if (res == -1) {
- return (-1);
- }
- case 3:
- /*
- * Read on heuristics cmd send fs shouldn't happen
- */
- break;
- }
-
- if (!case_processed) {
- log(LOG_CRIT, "Unhandled read on poll descriptor %u", i);
- exit(EXIT_FAILURE);
- }
- }
-
- if (pfds[i].revents & POLLOUT) {
- case_processed = 0;
- switch (i) {
- case 0:
- case 1:
- case 2:
- /*
- * Write on heuristics log, cmd recv or vq shouldn't happen
- */
- break;
- case 3:
- case_processed = 1;
- res = qdevice_heuristics_cmd_write(&instance->heuristics_instance);
- if (res == -1) {
- return (-1);
- }
- break;
- }
-
- if (!case_processed) {
- log(LOG_CRIT, "Unhandled write on poll descriptor %u", i);
- exit(EXIT_FAILURE);
- }
- }
-
- if ((pfds[i].revents & (POLLERR|POLLHUP|POLLNVAL)) &&
- !(pfds[i].revents & (POLLIN|POLLOUT))) {
- switch (i) {
- case 0:
- case 1:
- case 3:
- /*
- * Closed pipe doesn't mean return of POLLIN. To display
- * better log message, we call read log as if POLLIN would
- * be set.
- */
- res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
- if (res == -1) {
- return (-1);
- }
-
- log(LOG_ERR, "POLLERR (%u) on heuristics pipe. Exiting",
- pfds[i].revents);
- return (-1);
- break;
- case 2:
- log(LOG_ERR, "POLLERR (%u) on corosync socket. Exiting",
- pfds[i].revents);
- return (-1);
- break;
- }
- }
- }
- } else if (poll_res == 0) {
- log(LOG_ERR, "Timeout waiting for initial heuristics exec result");
- return (-1);
- } else {
- log_err(LOG_ERR, "Initial heuristics exec result poll failed");
- return (-1);
- }
- }
-
- return (0);
-}
/*
- * Copyright (c) 2015-2017 Red Hat, Inc.
+ * Copyright (c) 2015-2020 Red Hat, Inc.
*
* All rights reserved.
*
#include "qdevice-heuristics.h"
#include "qdevice-model-type.h"
#include "node-list.h"
+#include "pr-poll-loop.h"
#include "unix-socket-ipc.h"
#ifdef __cplusplus
int sync_in_progress;
struct qdevice_heuristics_instance heuristics_instance;
+
+ struct pr_poll_loop main_poll_loop;
+
+ /*
+ * Set by poll handler when votequorum connection is closed
+ */
+ int votequorum_closed;
+ /*
+ * Set by poll handler when one of the heuristics pipes becomes closed
+ */
+ int heuristics_closed;
};
extern int qdevice_instance_init(struct qdevice_instance *instance,
--- /dev/null
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log.h"
+#include "qdevice-heuristics-cmd.h"
+#include "qdevice-heuristics-log.h"
+#include "qdevice-pr-poll-loop-cb.h"
+#include "qdevice-votequorum.h"
+
+static int
+heuristics_pipe_log_recv_read_cb(int fd, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+ int res;
+
+ res = qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+ if (res == -1) {
+ instance->heuristics_closed = 1;
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Callback is shared for all heuristics pipes
+ */
+static int
+heuristics_pipe_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+
+ instance->heuristics_closed = 1;
+
+ /*
+ * Closed pipe doesn't mean return of PR_POLL_READ. To display
+ * better log message, we call read log as if POLLIN would
+ * be set. Ignore error code because loop closes anyway.
+ */
+ (void)qdevice_heuristics_log_read_from_pipe(&instance->heuristics_instance);
+ log(LOG_DEBUG, "POLL_ERR (%u) on heuristics pipe. "
+ "Disconnecting.", revents);
+
+ return (-1);
+}
+
+static int
+heuristics_pipe_cmd_recv_read_cb(int fd, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+ int res;
+
+ res = qdevice_heuristics_cmd_read_from_pipe(&instance->heuristics_instance);
+ if (res == -1) {
+ instance->heuristics_closed = 1;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+heuristics_pipe_cmd_send_set_events_cb(int fd, short *events, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+ int res;
+
+ res = -1;
+
+ if (!send_buffer_list_empty(&instance->heuristics_instance.cmd_out_buffer_list)) {
+ *events |= POLLOUT;
+ res = 0;
+ }
+
+ return (res);
+}
+
+static int
+heuristics_pipe_cmd_send_write_cb(int fd, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+ int res;
+
+ res = qdevice_heuristics_cmd_write(&instance->heuristics_instance);
+ if (res == -1) {
+ instance->heuristics_closed = 1;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+votequorum_read_cb(int fd, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+ int res;
+
+ res = qdevice_votequorum_dispatch(instance);
+ if (res == -1) {
+ instance->votequorum_closed = 1;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+votequorum_err_cb(int fd, short revents, void *user_data1, void *user_data2)
+{
+ struct qdevice_instance *instance = (struct qdevice_instance *)user_data1;
+
+ instance->votequorum_closed = 1;
+
+ log(LOG_DEBUG, "POLL_ERR (%u) on corosync socket. "
+ "Disconnecting.", revents);
+
+ return (-1);
+}
+
+int
+qdevice_pr_poll_loop_cb_register(struct qdevice_instance *instance)
+{
+
+ if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_log_recv,
+ POLLIN, NULL, heuristics_pipe_log_recv_read_cb, NULL, heuristics_pipe_err_cb,
+ instance, NULL) != 0) {
+ log(LOG_ERR, "Can't add heuristics log pipe to main poll loop");
+
+ return (-1);
+ }
+
+ if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_cmd_recv,
+ POLLIN, NULL, heuristics_pipe_cmd_recv_read_cb, NULL, heuristics_pipe_err_cb,
+ instance, NULL) != 0) {
+ log(LOG_ERR, "Can't add heuristics cmd recv pipe to main poll loop");
+
+ return (-1);
+ }
+
+ if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->heuristics_instance.pipe_cmd_send,
+ 0, heuristics_pipe_cmd_send_set_events_cb, NULL,
+ heuristics_pipe_cmd_send_write_cb, heuristics_pipe_err_cb,
+ instance, NULL) != 0) {
+ log(LOG_ERR, "Can't add heuristics cmd send pipe to main poll loop");
+
+ return (-1);
+ }
+
+ if (pr_poll_loop_add_fd(&instance->main_poll_loop, instance->votequorum_poll_fd,
+ POLLIN, NULL, votequorum_read_cb, NULL, votequorum_err_cb,
+ instance, NULL) != 0) {
+ log(LOG_ERR, "Can't add votequorum fd to main poll loop");
+
+ return (-1);
+ }
+
+ return (0);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_PR_POLL_LOOP_CB_H_
+#define _QDEVICE_PR_POLL_LOOP_CB_H_
+
+#include "qdevice-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int qdevice_pr_poll_loop_cb_register(struct qdevice_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_PR_POLL_LOOP_CB_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "log.h"
+#include "qdevice-pr-poll-loop.h"
+#include "timer-list.h"
+
+static int
+wait_for_initial_heuristics_exec_result_timeout_timer_cb(void *data1, void *data2)
+{
+ int *timeout_called = (int *)data1;
+
+ *timeout_called = 1;
+
+ return (0);
+}
+
+int
+qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(struct qdevice_instance *instance)
+{
+ struct timer_list_entry *timeout_timer;
+ int timeout_called;
+ int poll_res;
+ PRUint32 timeout;
+
+ timeout_called = 0;
+
+ /*
+ * We know this is never larger than QDEVICE_DEFAULT_HEURISTICS_MAX_TIMEOUT * 2
+ */
+ timeout = (PRUint32)instance->heuristics_instance.sync_timeout * 2;
+
+ timeout_timer = timer_list_add(pr_poll_loop_get_timer_list(&instance->main_poll_loop),
+ timeout, wait_for_initial_heuristics_exec_result_timeout_timer_cb,
+ &timeout_called, NULL);
+
+ while ((poll_res = pr_poll_loop_exec(&instance->main_poll_loop)) == 0 &&
+ !instance->vq_node_list_initial_heuristics_finished &&
+ !timeout_called) {
+ }
+
+ if (poll_res == -2) {
+ log(LOG_CRIT, "Initial heuristics exec result poll failed - internal error");
+ return (-1);
+ } else if (poll_res == -3) {
+ log_nss(LOG_CRIT, "Initial heuristics exec result poll failed - PR_Poll error");
+ return (-1);
+ }
+
+ if (timeout_called) {
+ log(LOG_ERR, "Timeout waiting for initial heuristics exec result");
+ return (-1);
+ }
+
+ timer_list_delete(pr_poll_loop_get_timer_list(&instance->main_poll_loop), timeout_timer);
+
+ return (poll_res);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2020 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+ * Author: Jan Friesse (jfriesse@redhat.com)
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of the Red Hat, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDEVICE_PR_POLL_LOOP_H_
+#define _QDEVICE_PR_POLL_LOOP_H_
+
+#include "qdevice-instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int qdevice_pr_poll_loop_wait_for_initial_heuristics_exec_result(
+ struct qdevice_instance *instance);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDEVICE_PR_POLL_LOOP_H_ */