[PATCH] fix waring produced by -Wp,-D_FORTIFY_SOURCE=2
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/ipc_us.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/ipc_us.c b/lib/ipc_us.c
index 8c64d5d..c64cd71 100644
--- a/lib/ipc_us.c
+++ b/lib/ipc_us.c
@@ -277,7 +277,7 @@ static int32_t qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_p
#endif
#if defined(QB_LINUX)
- snprintf(address.sun_path + 1, UNIX_PATH_MAX, "%s", socket_name);
+ snprintf(address.sun_path + 1, UNIX_PATH_MAX-1, "%s", socket_name);
#else
snprintf(address.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR, socket_name);
#endif
@@ -453,7 +453,7 @@ int32_t qb_ipcs_us_publish(struct qb_ipcs_service * s)
qb_util_log(LOG_INFO, "server name: %s", s->name);
#if defined(QB_LINUX)
- snprintf(un_addr.sun_path + 1, UNIX_PATH_MAX, "%s", s->name);
+ snprintf(un_addr.sun_path + 1, UNIX_PATH_MAX-1, "%s", s->name);
#else
{
struct stat stat_out;
--
1.7.3.1
13 years, 4 months
[PATCH 1/5] LOOP: prevent timers from deleting them selves.
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/ipcs.c | 2 +-
lib/loop_poll.c | 112 ++++++++++++++++++++++++++++++++++++++++-----------
tests/check_loop.c | 63 +++++++++++++++++++++++++++--
3 files changed, 147 insertions(+), 30 deletions(-)
diff --git a/lib/ipcs.c b/lib/ipcs.c
index e744f51..962bd09 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -176,7 +176,7 @@ void qb_ipcs_unref(struct qb_ipcs_service *s)
}
qb_ipcs_disconnect(c);
}
- qb_ipcs_us_withdraw(s);
+ (void)qb_ipcs_us_withdraw(s);
free(s);
}
}
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 2128dd0..8e667f9 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -55,6 +55,14 @@ enum qb_poll_type {
QB_JOB,
};
+enum qb_poll_entry_state {
+ QB_POLL_ENTRY_EMPTY,
+ QB_POLL_ENTRY_EXPIRED,
+ QB_POLL_ENTRY_DELETED,
+ QB_POLL_ENTRY_ACTIVE,
+};
+
+
struct qb_poll_entry;
typedef int32_t (*qb_poll_add_to_jobs_fn) (struct qb_loop* l, struct qb_poll_entry* pe);
@@ -68,6 +76,9 @@ struct qb_poll_entry {
int32_t install_pos;
struct pollfd ufd;
qb_poll_add_to_jobs_fn add_to_jobs;
+ uint32_t runs;
+ enum qb_poll_entry_state state;
+ qb_loop_timer_handle handle_addr;
};
struct qb_poll_source {
@@ -118,30 +129,48 @@ static void poll_dispatch_and_take_back(struct qb_loop_item * item,
#ifdef DEBUG_DISPATCH_TIME
uint64_t start;
uint64_t stop;
+ int32_t log_warn = QB_FALSE;
start = qb_util_nano_current_get();
#endif /* DEBUG_DISPATCH_TIME */
if (pe->type == QB_POLL) {
res = pe->poll_dispatch_fn(pe->ufd.fd, pe->ufd.revents, pe->item.user_data);
if (res < 0) {
+ pe->state = QB_POLL_ENTRY_EXPIRED;
pe->ufd.fd = -1; /* empty entry */
}
- pe->ufd.revents = 0;
} else {
+ pe->state = QB_POLL_ENTRY_EXPIRED;
+ memset(pe->handle_addr, 0, sizeof(struct qb_poll_entry *));
pe->timer_dispatch_fn(pe->item.user_data);
- if (pe->ufd.fd != -1) {
- close(pe->ufd.fd);
- pe->ufd.fd = -1; /* empty entry */
- pe->ufd.revents = 0;
- }
}
+ if (pe->state == QB_POLL_ENTRY_ACTIVE) {
+ pe->ufd.revents = 0;
#ifdef DEBUG_DISPATCH_TIME
- stop = qb_util_nano_current_get();
- if ((stop - start) > (10 * QB_TIME_NS_IN_MSEC)) {
- qb_util_log(LOG_WARNING, " dispatch function \"%p\" took %d ms",
- pe->poll_dispatch_fn, (int32_t)((stop - start)/QB_TIME_NS_IN_MSEC));
- }
+ pe->runs++;
+ if ((pe->runs % 50) == 0) {
+ log_warn = QB_TRUE;
+ }
+ stop = qb_util_nano_current_get();
+ if ((stop - start) > (10 * QB_TIME_NS_IN_MSEC)) {
+ log_warn = QB_TRUE;
+ }
+
+ if (log_warn && pe->type == QB_POLL) {
+ qb_util_log(LOG_INFO,
+ "[fd:%d] dispatch:%p runs:%d duration:%d ms",
+ pe->ufd.fd, pe->poll_dispatch_fn,
+ pe->runs,
+ (int32_t)((stop - start)/QB_TIME_NS_IN_MSEC));
+ } else if (log_warn && pe->type == QB_TIMER) {
+ qb_util_log(LOG_INFO,
+ "[timer] dispatch:%p runs:%d duration:%d ms",
+ pe->timer_dispatch_fn,
+ pe->runs,
+ (int32_t)((stop - start)/QB_TIME_NS_IN_MSEC));
+ }
#endif /* DEBUG_DISPATCH_TIME */
+ }
}
static void poll_fds_usage_check(struct qb_poll_source *s)
@@ -170,7 +199,7 @@ static void poll_fds_usage_check(struct qb_poll_source *s)
for (i = 0; i < s->poll_entry_count; i++) {
assert(qb_array_index(s->poll_entries, i, (void**)&pe) == 0);
- if (pe->ufd.fd != -1) {
+ if (pe->state == QB_POLL_ENTRY_ACTIVE && pe->ufd.fd != -1) {
socks_used++;
}
}
@@ -197,7 +226,7 @@ static void poll_fds_usage_check(struct qb_poll_source *s)
}
#ifdef HAVE_EPOLL
-#define MAX_EVENTS 100
+#define MAX_EVENTS 12
static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeout)
{
int32_t i;
@@ -209,6 +238,14 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
poll_fds_usage_check(s);
+ for (i = 0; i < s->poll_entry_count; i++) {
+ assert(qb_array_index(s->poll_entries, i, (void**)&pe) == 0);
+ if (pe->state == QB_POLL_ENTRY_DELETED ||
+ pe->state == QB_POLL_ENTRY_EXPIRED) {
+ pe->state = QB_POLL_ENTRY_EMPTY;
+ }
+ }
+
retry_poll:
res = epoll_wait(s->epollfd, events, MAX_EVENTS, ms_timeout);
@@ -250,6 +287,11 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
for (i = 0; i < s->poll_entry_count; i++) {
assert(qb_array_index(s->poll_entries, i, (void**)&pe) == 0);
memcpy(&s->ufds[i], &pe->ufd, sizeof(struct pollfd));
+
+ if (pe->state == QB_POLL_ENTRY_DELETED ||
+ pe->state == QB_POLL_ENTRY_EXPIRED) {
+ pe->state = QB_POLL_ENTRY_EMPTY;
+ }
}
retry_poll:
@@ -339,7 +381,7 @@ static int32_t _get_empty_array_position_(struct qb_poll_source * s)
for (found = 0, install_pos = 0;
install_pos < s->poll_entry_count; install_pos++) {
assert(qb_array_index(s->poll_entries, install_pos, (void**)&pe) == 0);
- if (pe->ufd.fd == -1) {
+ if (pe->state == QB_POLL_ENTRY_EMPTY) {
found = 1;
break;
}
@@ -402,6 +444,7 @@ static int32_t _poll_add_(struct qb_loop *l,
install_pos = _get_empty_array_position_(s);
assert(qb_array_index(s->poll_entries, install_pos, (void**)&pe) == 0);
+ pe->state = QB_POLL_ENTRY_ACTIVE;
pe->install_pos = install_pos;
pe->ufd.fd = fd;
pe->ufd.events = events;
@@ -409,6 +452,7 @@ static int32_t _poll_add_(struct qb_loop *l,
pe->item.user_data = data;
pe->item.source = (struct qb_loop_source*)l->fd_source;
pe->p = p;
+ pe->runs = 0;
#ifdef HAVE_EPOLL
ev = &s->events[install_pos];
ev->events = poll_to_epoll_event(events);
@@ -424,6 +468,23 @@ static int32_t _poll_add_(struct qb_loop *l,
return (res);
}
+static int32_t _qb_timer_add_to_jobs_(struct qb_loop* l, struct qb_poll_entry* pe)
+{
+ uint64_t expired = 0;
+
+ if (pe->ufd.revents == POLLIN) {
+ (void)read(pe->ufd.fd, &expired, sizeof(expired));
+ qb_list_init(&pe->item.list);
+ qb_list_add_tail(&pe->item.list, &l->level[pe->p].job_head);
+ } else {
+ qb_util_log(LOG_ERR, "timer revents: %d expected %d",
+ pe->ufd.revents, POLLIN);
+ }
+ close(pe->ufd.fd);
+ pe->ufd.fd = -1;
+ return 1;
+}
+
static int32_t _qb_poll_add_to_jobs_(struct qb_loop* l, struct qb_poll_entry* pe)
{
qb_list_init(&pe->item.list);
@@ -503,6 +564,7 @@ int32_t qb_loop_poll_del(struct qb_loop *l, int32_t fd)
continue;
}
pe->ufd.fd = -1;
+ pe->state = QB_POLL_ENTRY_DELETED;
pe->ufd.events = 0;
pe->ufd.revents = 0;
#ifdef HAVE_EPOLL
@@ -579,16 +641,16 @@ int32_t qb_loop_timer_add(struct qb_loop *l,
}
res = _poll_add_(l, p, fd, POLLIN, data, &pe);
- if (res == -1) {
- res = -errno;
+ if (res != 0) {
qb_util_log(LOG_ERR, "_poll_add_() : %s",
strerror(-res));
goto close_and_return;
}
pe->timer_dispatch_fn = timer_fn;
pe->type = QB_TIMER;
- pe->add_to_jobs = _qb_poll_add_to_jobs_;
+ pe->add_to_jobs = _qb_timer_add_to_jobs_;
*timer_handle_out = pe;
+ pe->handle_addr = timer_handle_out;
return res;
@@ -614,27 +676,29 @@ int32_t qb_loop_timer_del(struct qb_loop *l, qb_loop_timer_handle th)
if (pe->type != QB_TIMER) {
return -EINVAL;
}
+ memset(pe->handle_addr, 0, sizeof(struct qb_poll_entry *));
+ if (pe->state != QB_POLL_ENTRY_ACTIVE &&
+ pe->state != QB_POLL_ENTRY_EXPIRED) {
+ return -EINVAL;
+ }
if (pe->ufd.fd != -1) {
#ifdef HAVE_EPOLL
if (epoll_ctl(s->epollfd, EPOLL_CTL_DEL, pe->ufd.fd, NULL) == -1) {
res = -errno;
qb_util_log(LOG_ERR, "epoll_ctl(del:%d) : %s",
pe->ufd.fd, strerror(-res));
- return res;
}
#else
s->ufds[pe->install_pos].fd = -1;
s->ufds[pe->install_pos].events = 0;
s->ufds[pe->install_pos].revents = 0;
#endif /* HAVE_EPOLL */
- if (pe->ufd.fd != -1) {
- close(pe->ufd.fd);
- }
-
+ close(pe->ufd.fd);
pe->ufd.fd = -1;
- pe->ufd.events = 0;
- pe->ufd.revents = 0;
}
+ pe->ufd.events = 0;
+ pe->ufd.revents = 0;
+ pe->state = QB_POLL_ENTRY_DELETED;
return 0;
}
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 18edbcc..274da97 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -180,17 +180,17 @@ static Suite *loop_job_suite(void)
* -----------------------------------------------------------------------
* Timers
*/
+static qb_loop_timer_handle test_th;
START_TEST(test_loop_timer_input)
{
int32_t res;
- qb_loop_timer_handle th;
qb_loop_t *l = qb_loop_create();
fail_if(l == NULL);
- res = qb_loop_timer_add(NULL, QB_LOOP_LOW, 5, NULL, job_2, &th);
+ res = qb_loop_timer_add(NULL, QB_LOOP_LOW, 5, NULL, job_2, &test_th);
ck_assert_int_eq(res, -EINVAL);
- res = qb_loop_timer_add(l, QB_LOOP_LOW, 5, l, NULL, &th);
+ res = qb_loop_timer_add(l, QB_LOOP_LOW, 5, l, NULL, &test_th);
ck_assert_int_eq(res, -EINVAL);
res = qb_loop_timer_add(l, QB_LOOP_LOW, 5, l, job_1, NULL);
ck_assert_int_eq(res, -ENOENT);
@@ -198,6 +198,52 @@ START_TEST(test_loop_timer_input)
}
END_TEST
+static void one_shot_tmo(void*data)
+{
+ static int32_t been_here = QB_FALSE;
+ ck_assert_int_eq(been_here, QB_FALSE);
+ been_here = QB_TRUE;
+}
+
+static qb_loop_timer_handle reset_th;
+static int32_t reset_timer_step = 0;
+static void reset_one_shot_tmo(void*data)
+{
+ int32_t res;
+ qb_loop_t *l = data;
+ if (reset_timer_step == 0) {
+ res = qb_loop_timer_del(l, reset_th);
+ ck_assert_int_eq(res, -EINVAL);
+ res = qb_loop_timer_add(l, QB_LOOP_LOW, 8, l, reset_one_shot_tmo, &reset_th);
+ ck_assert_int_eq(res, 0);
+ }
+
+ reset_timer_step++;
+}
+
+START_TEST(test_loop_timer_basic)
+{
+ int32_t res;
+ qb_loop_t *l = qb_loop_create();
+ fail_if(l == NULL);
+
+ res = qb_loop_timer_add(l, QB_LOOP_LOW, 5, l, one_shot_tmo, &test_th);
+ ck_assert_int_eq(res, 0);
+
+ res = qb_loop_timer_add(l, QB_LOOP_LOW, 7, l, reset_one_shot_tmo, &reset_th);
+ ck_assert_int_eq(res, 0);
+
+ res = qb_loop_timer_add(l, QB_LOOP_LOW, 60, l, job_stop, &test_th);
+ ck_assert_int_eq(res, 0);
+
+ qb_loop_run(l);
+
+ ck_assert_int_eq(reset_timer_step, 2);
+
+ qb_loop_destroy(l);
+}
+END_TEST
+
struct qb_stop_watch {
uint64_t start;
uint64_t end;
@@ -217,8 +263,10 @@ static void stop_watch_tmo(void*data)
sw->end = qb_util_nano_current_get();
diff = sw->end - sw->start;
+ if (diff < (sw->ms_timer * QB_TIME_NS_IN_MSEC)) {
+ printf("timer expired early! by %lld\n", (sw->ms_timer * QB_TIME_NS_IN_MSEC) - diff);
+ }
ck_assert(diff >= (sw->ms_timer * QB_TIME_NS_IN_MSEC));
-
sw->total += diff;
sw->total -= sw->ms_timer * QB_TIME_NS_IN_MSEC;
sw->start = sw->end;
@@ -251,7 +299,7 @@ static void start_timer(qb_loop_t *l, struct qb_stop_watch *sw, int32_t timeout)
}
-START_TEST(test_loop_timer_basic)
+START_TEST(test_loop_timer_precision)
{
int32_t i;
int32_t tmo;
@@ -285,6 +333,11 @@ static Suite *loop_timer_suite(void)
tcase_set_timeout(tc, 30);
suite_add_tcase(s, tc);
+ tc = tcase_create("precision");
+ tcase_add_test(tc, test_loop_timer_precision);
+ tcase_set_timeout(tc, 30);
+ suite_add_tcase(s, tc);
+
return s;
}
--
1.7.3.1
13 years, 4 months
[PATCH] IPC: withdraw server socket when destroying a service.
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/ipcs.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/lib/ipcs.c b/lib/ipcs.c
index 3152dfe..e744f51 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -176,6 +176,7 @@ void qb_ipcs_unref(struct qb_ipcs_service *s)
}
qb_ipcs_disconnect(c);
}
+ qb_ipcs_us_withdraw(s);
free(s);
}
}
--
1.7.3.1
13 years, 4 months
[PATCH 1/3] UTIL: check for shm usable space.
by Angus Salkeld
- port corosync write() check
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/util.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/lib/util.c b/lib/util.c
index 336b4a9..0452354 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -248,6 +248,10 @@ int32_t qb_util_mmap_file_open(char *path, const char *file, size_t bytes,
uint32_t file_flags)
{
int32_t fd;
+ int32_t i;
+ int32_t res = 0;
+ ssize_t written;
+ char *buffer = NULL;
char *is_absolute = strchr(file, '/');;
if (is_absolute) {
@@ -257,25 +261,57 @@ int32_t qb_util_mmap_file_open(char *path, const char *file, size_t bytes,
}
fd = open_mmap_file(path, file_flags);
if (fd < 0 && !is_absolute) {
+ res = -errno;
qb_util_log(LOG_ERR, "couldn't open file %s error: %s",
- path, strerror(errno));
+ path, strerror(-res));
snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file);
fd = open_mmap_file(path, file_flags);
if (fd < 0) {
+ res = -errno;
qb_util_log(LOG_ERR, "couldn't open file %s error: %s",
- path, strerror(errno));
- return -errno;
+ path, strerror(-res));
+ return res;
}
}
- if (fd >= 0) {
- ftruncate(fd, bytes);
- } else {
- qb_util_log(LOG_ERR, "couldn't open file %s error: %s",
- path, strerror(errno));
+ if (ftruncate(fd, bytes) == -1) {
+ res = -errno;
+ qb_util_log(LOG_ERR,
+ "couldn't truncate file %s error: %s",
+ path, strerror(-res));
+ goto unlink_exit;
}
+
+
+ if (file_flags & O_CREAT) {
+ long page_size = sysconf(_SC_PAGESIZE);
+ buffer = calloc(1, page_size);
+ if (buffer == NULL) {
+ goto unlink_exit;
+ }
+ for (i = 0; i < (bytes / page_size); i++) {
+retry_write:
+ written = write (fd, buffer, page_size);
+ if (written == -1 && errno == EINTR) {
+ goto retry_write;
+ }
+ if (written != page_size) {
+ free (buffer);
+ goto unlink_exit;
+ }
+ }
+ free (buffer);
+ }
+
return fd;
+
+unlink_exit:
+ unlink (path);
+ if (fd > 0) {
+ close (fd);
+ }
+ return res;
}
int32_t qb_util_circular_mmap(int32_t fd, void **buf, size_t bytes)
--
1.7.3.1
13 years, 4 months
[PATCH] LOOP: add signal support to main loop
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbloop.h | 55 ++++++++++-
lib/loop.c | 8 +-
lib/loop_int.h | 5 +
lib/loop_poll.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++---
tests/check_loop.c | 13 +--
tests/loop.c | 21 ++++
6 files changed, 352 insertions(+), 29 deletions(-)
diff --git a/include/qb/qbloop.h b/include/qb/qbloop.h
index 026b2be..f8d0b55 100644
--- a/include/qb/qbloop.h
+++ b/include/qb/qbloop.h
@@ -21,6 +21,8 @@
#ifndef QB_LOOP_DEFINED
#define QB_LOOP_DEFINED
+#include <signal.h>
+
/**
* @file qbloop.h
*
@@ -42,12 +44,13 @@ enum qb_loop_priority {
*/
typedef struct qb_loop qb_loop_t;
-typedef void *qb_loop_job_handle;
typedef void *qb_loop_timer_handle;
+typedef void *qb_loop_signal_handle;
typedef int32_t (*qb_loop_poll_dispatch_fn) (int32_t fd, int32_t revents, void *data);
typedef void (*qb_loop_job_dispatch_fn)(void *data);
typedef void (*qb_loop_timer_dispatch_fn)(void *data);
+typedef int32_t (*qb_loop_signal_dispatch_fn)(int32_t rsignal, void *data);
typedef void (*qb_loop_poll_low_fds_event_fn) (int32_t not_enough, int32_t fds_available);
@@ -141,8 +144,6 @@ uint64_t qb_loop_timer_expire_time_get(struct qb_loop *l, qb_loop_timer_handle t
int32_t qb_loop_poll_low_fds_event_set(qb_loop_t *l,
qb_loop_poll_low_fds_event_fn fn);
-
-
/**
* Add a poll job to the mainloop.
* @note it is a re-occuring job.
@@ -189,5 +190,53 @@ int32_t qb_loop_poll_mod(qb_loop_t *l,
*/
int32_t qb_loop_poll_del(qb_loop_t *l, int32_t fd);
+/**
+ * Add a signal job.
+ *
+ * Get a callback on this signal (not in the context of the signal).
+ *
+ * @param l pointer to the loop instance
+ * @param p the priority
+ * @param signal (SIGHUP or SIGINT) etc ....
+ * @param data user data passed into the dispatch function
+ * @param dispatch_fn callback function
+ * @param handle (out) a reference to the signal job
+ * @return status (0 == ok, -errno == failure)
+ */
+int32_t qb_loop_signal_add(qb_loop_t *l,
+ enum qb_loop_priority p,
+ int32_t signal,
+ void *data,
+ qb_loop_signal_dispatch_fn dispatch_fn,
+ qb_loop_signal_handle *handle);
+
+/**
+ * Modify the signal job
+ *
+ * @param l pointer to the loop instance
+ * @param p the priority
+ * @param signal (SIGHUP or SIGINT) etc ....
+ * @param data user data passed into the dispatch function
+ * @param dispatch_fn callback function
+ * @param handle (in) a reference to the signal job
+ * @return status (0 == ok, -errno == failure)
+ */
+int32_t qb_loop_signal_mod(qb_loop_t *l,
+ enum qb_loop_priority p,
+ int32_t signal,
+ void *data,
+ qb_loop_signal_dispatch_fn dispatch_fn,
+ qb_loop_signal_handle handle);
+
+/**
+ * Delete the signal job.
+ *
+ * @param l pointer to the loop instance
+ * @param handle (in) a reference to the signal job
+ * @return status (0 == ok, -errno == failure)
+ */
+int32_t qb_loop_signal_del(qb_loop_t *l,
+ qb_loop_signal_handle handle);
+
#endif /* QB_LOOP_DEFINED */
diff --git a/lib/loop.c b/lib/loop.c
index 7f7cf74..6eb802d 100644
--- a/lib/loop.c
+++ b/lib/loop.c
@@ -70,6 +70,7 @@ struct qb_loop * qb_loop_create(void)
l->timer_source = qb_loop_timer_create(l);
l->job_source = qb_loop_jobs_create(l);
l->fd_source = qb_loop_poll_create(l);
+ l->signal_source = qb_loop_signals_create(l);
return l;
}
@@ -79,6 +80,7 @@ void qb_loop_destroy(struct qb_loop * l)
qb_loop_timer_destroy(l);
qb_loop_jobs_destroy(l);
qb_loop_poll_destroy(l);
+ qb_loop_signals_destroy(l);
free(l);
}
@@ -101,8 +103,10 @@ void qb_loop_run(struct qb_loop *l)
p_stop--;
}
- todo += l->job_source->poll(l->job_source, 0);
- if (l->timer_source) {
+ if (l->job_source && l->job_source->poll) {
+ todo += l->job_source->poll(l->job_source, 0);
+ }
+ if (l->timer_source && l->timer_source->poll) {
todo += l->timer_source->poll(l->timer_source, 0);
}
if (todo > 0) {
diff --git a/lib/loop_int.h b/lib/loop_int.h
index d3146e0..e9da182 100644
--- a/lib/loop_int.h
+++ b/lib/loop_int.h
@@ -54,6 +54,7 @@ struct qb_loop {
struct qb_loop_source * timer_source;
struct qb_loop_source * job_source;
struct qb_loop_source * fd_source;
+ struct qb_loop_source * signal_source;
};
struct qb_loop_source *
@@ -65,12 +66,16 @@ qb_loop_timer_create(struct qb_loop *l);
struct qb_loop_source*
qb_loop_poll_create(struct qb_loop *l);
+struct qb_loop_source *
+qb_loop_signals_create(struct qb_loop *l);
+
void qb_loop_jobs_destroy(struct qb_loop *l);
void qb_loop_timer_destroy(struct qb_loop *l);
void qb_loop_poll_destroy(struct qb_loop *l);
+void qb_loop_signals_destroy(struct qb_loop *l);
int32_t qb_loop_timer_msec_duration_to_expire(struct qb_loop_source *timer_source);
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 2067f9c..d74f296 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -30,6 +30,7 @@
#include <sys/timerfd.h>
#endif /* HAVE_SYS_TIMERFD_H */
#endif /* S_SPLINT_S */
+#include <signal.h>
#include <qb/qbdefs.h>
#include <qb/qblist.h>
@@ -46,17 +47,23 @@
enum qb_poll_type {
QB_POLL,
QB_TIMER,
+ QB_SIGNAL,
+ QB_JOB,
};
+struct qb_poll_entry;
+
+typedef int32_t (*qb_poll_add_to_jobs_fn) (struct qb_loop* l, struct qb_poll_entry* pe);
struct qb_poll_entry {
struct qb_loop_item item;
- struct pollfd ufd;
+ enum qb_poll_type type;
qb_loop_poll_dispatch_fn poll_dispatch_fn;
qb_loop_timer_dispatch_fn timer_dispatch_fn;
enum qb_loop_priority p;
int32_t install_pos;
- enum qb_poll_type type;
+ struct pollfd ufd;
+ qb_poll_add_to_jobs_fn add_to_jobs;
};
struct qb_poll_source {
@@ -100,7 +107,7 @@ static int32_t epoll_to_poll_event(int32_t event)
#endif /* HAVE_EPOLL */
static void poll_dispatch_and_take_back(struct qb_loop_item * item,
- enum qb_loop_priority p)
+ enum qb_loop_priority p)
{
struct qb_poll_entry *pe = (struct qb_poll_entry *)item;
int32_t res;
@@ -207,9 +214,8 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
continue;
}
pe->ufd.revents = epoll_to_poll_event(events[i].events);
- qb_list_init(&pe->item.list);
- qb_list_add_tail(&pe->item.list, &s->s.l->level[pe->p].job_head);
- new_jobs++;
+
+ new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
@@ -249,9 +255,7 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
continue;
}
pe->ufd.revents = s->ufds[i].revents;
- qb_list_init(&pe->item.list);
- qb_list_add_tail(&pe->item.list, &s->s.l->level[pe->p].job_head);
- new_jobs++;
+ new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
@@ -286,14 +290,16 @@ void qb_loop_poll_destroy(struct qb_loop *l)
struct qb_poll_source * s = (struct qb_poll_source *)l->fd_source;
qb_array_free(s->poll_entries);
#ifdef HAVE_EPOLL
- close(s->epollfd);
+ if (s->epollfd != -1) {
+ close(s->epollfd);
+ s->epollfd = -1;
+ }
#endif /* HAVE_EPOLL */
free(s);
}
-int32_t qb_loop_poll_low_fds_event_set(
- qb_loop_t *l,
- qb_loop_poll_low_fds_event_fn fn)
+int32_t qb_loop_poll_low_fds_event_set(struct qb_loop *l,
+ qb_loop_poll_low_fds_event_fn fn)
{
struct qb_poll_source * s = (struct qb_poll_source *)l->fd_source;
s->low_fds_event_fn = fn;
@@ -301,7 +307,7 @@ int32_t qb_loop_poll_low_fds_event_set(
return 0;
}
-static int32_t new_array_position_get(struct qb_poll_source * s)
+static int32_t _get_empty_array_position_(struct qb_poll_source * s)
{
int32_t found = 0;
int32_t install_pos;
@@ -377,7 +383,7 @@ static int32_t _poll_add_(struct qb_loop *l,
s = (struct qb_poll_source *)l->fd_source;
- install_pos = new_array_position_get(s);
+ install_pos = _get_empty_array_position_(s);
assert(qb_array_index(s->poll_entries, install_pos, (void**)&pe) == 0);
pe->install_pos = install_pos;
@@ -402,6 +408,13 @@ static int32_t _poll_add_(struct qb_loop *l,
return (res);
}
+static int32_t _qb_poll_add_to_jobs_(struct qb_loop* l, struct qb_poll_entry* pe)
+{
+ qb_list_init(&pe->item.list);
+ qb_list_add_tail(&pe->item.list, &l->level[pe->p].job_head);
+ return 1;
+}
+
int32_t qb_loop_poll_add(struct qb_loop *l,
enum qb_loop_priority p,
int32_t fd,
@@ -413,6 +426,7 @@ int32_t qb_loop_poll_add(struct qb_loop *l,
int32_t res = _poll_add_(l, p, fd, events, data, &pe);
pe->poll_dispatch_fn = dispatch_fn;
pe->type = QB_POLL;
+ pe->add_to_jobs = _qb_poll_add_to_jobs_;
return res;
}
@@ -495,7 +509,7 @@ int32_t qb_loop_poll_del(struct qb_loop *l, int32_t fd)
#ifdef HAVE_TIMERFD
int32_t qb_loop_timer_msec_duration_to_expire(struct qb_loop_source *timer_source)
{
- return 0;
+ return -1;
}
struct qb_loop_source*
@@ -557,6 +571,7 @@ int32_t qb_loop_timer_add(struct qb_loop *l,
}
pe->timer_dispatch_fn = timer_fn;
pe->type = QB_TIMER;
+ pe->add_to_jobs = _qb_poll_add_to_jobs_;
*timer_handle_out = pe;
return res;
@@ -596,7 +611,9 @@ int32_t qb_loop_timer_del(struct qb_loop *l, qb_loop_timer_handle th)
s->ufds[pe->install_pos].events = 0;
s->ufds[pe->install_pos].revents = 0;
#endif /* HAVE_EPOLL */
- close(pe->ufd.fd);
+ if (pe->ufd.fd != -1) {
+ close(pe->ufd.fd);
+ }
pe->ufd.fd = -1;
pe->ufd.events = 0;
@@ -624,3 +641,231 @@ uint64_t qb_loop_timer_expire_time_get(struct qb_loop *l, qb_loop_timer_handle t
#endif /* HAVE_TIMERFD */
+
+static int32_t pipe_fds[2] = {-1, -1};
+
+struct qb_signal_source {
+ struct qb_loop_source s;
+ struct qb_list_head sig_head;
+ sigset_t signal_superset;
+};
+
+struct qb_loop_sig {
+ struct qb_loop_item item;
+ int32_t signal;
+ enum qb_loop_priority p;
+ qb_loop_signal_dispatch_fn dispatch_fn;
+ struct qb_loop_sig *cloned_from;
+};
+
+static void _handle_real_signal_(int signal_num, siginfo_t * si, void *context)
+{
+ int32_t sig = signal_num;
+ if (pipe_fds[1] > 0) {
+ (void)write(pipe_fds[1], &sig, sizeof(int32_t));
+ }
+}
+
+static void signal_dispatch_and_take_back(struct qb_loop_item * item,
+ enum qb_loop_priority p)
+{
+ struct qb_loop_sig *sig = (struct qb_loop_sig *)item;
+ int32_t res;
+
+ res = sig->dispatch_fn(sig->signal, sig->item.user_data);
+ if (res != 0) {
+ qb_list_del(&sig->cloned_from->item.list);
+ free(sig->cloned_from);
+ }
+ free(sig);
+}
+
+
+struct qb_loop_source *
+qb_loop_signals_create(struct qb_loop *l)
+{
+ struct qb_signal_source *s = calloc(1, sizeof(struct qb_signal_source));
+ s->s.l = l;
+ s->s.dispatch_and_take_back = signal_dispatch_and_take_back;
+ s->s.poll = NULL;
+ qb_list_init(&s->sig_head);
+ sigemptyset(&s->signal_superset);
+
+ return (struct qb_loop_source *)s;
+}
+
+void qb_loop_signals_destroy(struct qb_loop *l)
+{
+ close(pipe_fds[0]);
+ pipe_fds[0] = -1;
+ close(pipe_fds[1]);
+ pipe_fds[1] = -1;
+ free(l->signal_source);
+}
+
+static int32_t _qb_signal_add_to_jobs_(struct qb_loop* l,
+ struct qb_poll_entry* pe)
+{
+ struct qb_signal_source *s = (struct qb_signal_source *)l->signal_source;
+ struct qb_list_head *list;
+ struct qb_loop_sig *sig;
+ struct qb_loop_item *item;
+ struct qb_loop_sig *new_sig_job;
+ int32_t the_signal;
+ ssize_t res;
+ int32_t jobs_added = 0;
+
+ res = read(pipe_fds[0], &the_signal, sizeof(int32_t));
+ if (res != sizeof(int32_t)) {
+ res = -errno;
+ qb_util_log(LOG_ERR, "failed to read pipe: %s", strerror(errno));
+ return 0;
+ }
+ pe->ufd.revents = 0;
+
+ qb_list_for_each(list, &s->sig_head) {
+ item = qb_list_entry(list, struct qb_loop_item, list);
+ sig = (struct qb_loop_sig *)item;
+ if (sig->signal == the_signal) {
+ new_sig_job = calloc(1, sizeof(struct qb_loop_sig));
+ memcpy(new_sig_job, sig, sizeof(struct qb_loop_sig));
+
+ new_sig_job->cloned_from = sig;
+ qb_list_init(&new_sig_job->item.list);
+ qb_list_add_tail(&new_sig_job->item.list,
+ &l->level[pe->p].job_head);
+ jobs_added++;
+ }
+ }
+ return jobs_added;
+}
+
+static void _adjust_sigactions_(struct qb_signal_source *s)
+{
+ struct qb_loop_sig *sig;
+ struct qb_loop_item *item;
+ struct sigaction sa;
+ int32_t i;
+ int32_t needed;
+
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = _handle_real_signal_;
+ sigemptyset(&s->signal_superset);
+ sigemptyset(&sa.sa_mask);
+
+ /* re-set to default */
+ for (i = 0; i < 30; i++) {
+ needed = QB_FALSE;
+ qb_list_for_each_entry(item, &s->sig_head, list) {
+ sig = (struct qb_loop_sig *)item;
+ if (i == sig->signal) {
+ needed = QB_TRUE;
+ break;
+ }
+ }
+ if (needed) {
+ sigaddset(&s->signal_superset, i);
+ sigaction(i, &sa, NULL);
+ } else {
+ (void)signal(i, SIG_DFL);
+ }
+ }
+}
+
+int32_t qb_loop_signal_add(qb_loop_t *l,
+ enum qb_loop_priority p,
+ int32_t the_sig,
+ void *data,
+ qb_loop_signal_dispatch_fn dispatch_fn,
+ qb_loop_signal_handle *handle)
+{
+ struct qb_loop_sig *sig;
+ struct qb_poll_entry *pe;
+ struct qb_signal_source *s;
+ int32_t res = 0;
+
+ if (l == NULL || dispatch_fn == NULL) {
+ return -EINVAL;
+ }
+ if (p < QB_LOOP_LOW || p > QB_LOOP_HIGH) {
+ return -EINVAL;
+ }
+ s = (struct qb_signal_source *)l->signal_source;
+ sig = calloc(1, sizeof(struct qb_loop_sig));
+
+ sig->dispatch_fn = dispatch_fn;
+ sig->p = p;
+ sig->signal = the_sig;
+ sig->item.user_data = data;
+ sig->item.source = l->signal_source;
+
+ qb_list_init(&sig->item.list);
+ qb_list_add_tail(&sig->item.list, &s->sig_head);
+
+ if (pipe_fds[0] < 0) {
+ pipe(pipe_fds);
+ res = _poll_add_(l, QB_LOOP_HIGH,
+ pipe_fds[0], POLLIN,
+ NULL, &pe);
+ if (res == 0) {
+ pe->poll_dispatch_fn = NULL;
+ pe->type = QB_SIGNAL;
+ pe->add_to_jobs = _qb_signal_add_to_jobs_;
+ } else {
+ qb_util_log(LOG_ERR,
+ "failed to setup pipe: %s",
+ strerror(-res));
+ }
+ }
+
+ if (sigismember(&s->signal_superset, the_sig) != 1) {
+ _adjust_sigactions_(s);
+ }
+ if (handle) {
+ *handle = sig;
+ }
+
+ return 0;
+}
+
+int32_t qb_loop_signal_mod(qb_loop_t *l,
+ enum qb_loop_priority p,
+ int32_t the_sig,
+ void *data,
+ qb_loop_signal_dispatch_fn dispatch_fn,
+ qb_loop_signal_handle handle)
+{
+ struct qb_signal_source *s;
+ struct qb_loop_sig *sig = (struct qb_loop_sig *)handle;
+
+ if (l == NULL || dispatch_fn == NULL || handle == NULL) {
+ return -EINVAL;
+ }
+ if (p < QB_LOOP_LOW || p > QB_LOOP_HIGH) {
+ return -EINVAL;
+ }
+ s = (struct qb_signal_source *)l->signal_source;
+
+ sig->item.user_data = data;
+ sig->dispatch_fn = dispatch_fn;
+ sig->p = p;
+
+ if (sig->signal != the_sig) {
+ sig->signal = the_sig;
+ _adjust_sigactions_(s);
+ }
+
+ return 0;
+}
+
+int32_t qb_loop_signal_del(qb_loop_t *l,
+ qb_loop_signal_handle handle)
+{
+ struct qb_loop_sig *sig = (struct qb_loop_sig *)handle;
+
+ qb_list_del(&sig->item.list);
+ free(sig);
+ return 0;
+}
+
+
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 0f82b30..f34e026 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -205,13 +205,13 @@ struct qb_stop_watch {
int32_t ms_timer;
int64_t total;
int32_t count;
+ qb_loop_timer_handle th;
};
static void stop_watch_tmo(void*data)
{
- qb_loop_timer_handle th;
struct qb_stop_watch *sw = (struct qb_stop_watch *)data;
- int64_t per;
+ float per;
sw->end = qb_util_nano_current_get();
sw->total += sw->end - sw->start;
@@ -219,10 +219,10 @@ static void stop_watch_tmo(void*data)
sw->start = sw->end;
sw->count++;
if (sw->count < 50) {
- qb_loop_timer_add(sw->l, QB_LOOP_LOW, sw->ms_timer, data, stop_watch_tmo, &th);
+ qb_loop_timer_add(sw->l, QB_LOOP_LOW, sw->ms_timer, data, stop_watch_tmo, &sw->th);
} else {
- per = (sw->total / sw->count) * 100 / (sw->ms_timer * QB_TIME_NS_IN_MSEC);
- printf("average error for %d ms timer is %"PRIi64" (ns) (%"PRIi64"%%)\n",
+ per = ((sw->total * 100) / sw->count) / (sw->ms_timer * (float)QB_TIME_NS_IN_MSEC);
+ printf("average error for %d ms timer is %"PRIi64" (ns) (%f)\n",
sw->ms_timer,
sw->total/sw->count, per);
if (sw->ms_timer == 100) {
@@ -233,7 +233,6 @@ static void stop_watch_tmo(void*data)
static void start_timer(qb_loop_t *l, struct qb_stop_watch *sw, int32_t timeout)
{
- qb_loop_timer_handle th;
int32_t res;
sw->l = l;
@@ -241,7 +240,7 @@ static void start_timer(qb_loop_t *l, struct qb_stop_watch *sw, int32_t timeout)
sw->total = 0;
sw->ms_timer = timeout;
sw->start = qb_util_nano_current_get();
- res = qb_loop_timer_add(sw->l, QB_LOOP_LOW, sw->ms_timer, sw, stop_watch_tmo, &th);
+ res = qb_loop_timer_add(sw->l, QB_LOOP_LOW, sw->ms_timer, sw, stop_watch_tmo, &sw->th);
ck_assert_int_eq(res, 0);
}
diff --git a/tests/loop.c b/tests/loop.c
index 38c959e..f920ffb 100644
--- a/tests/loop.c
+++ b/tests/loop.c
@@ -19,6 +19,8 @@
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
+#include <signal.h>
+
#include <sys/poll.h>
#include <qb/qbloop.h>
@@ -45,6 +47,19 @@ static void more_important_jobs(void *data)
qb_loop_job_add(l, QB_LOOP_HIGH, NULL, job_1_9);
}
+static int32_t handle_reconf_signal(int32_t sig, void *data)
+{
+ printf("%s(%d) \n", __func__, sig);
+ return 0;
+}
+
+static int32_t handle_exit_signal(int32_t sig, void *data)
+{
+ printf("%s(%d) exiting ... bye\n", __func__, sig);
+ qb_loop_stop(l);
+ return -1;
+}
+
static void more_jobs(void *data)
{
printf("%s\n", __func__);
@@ -82,6 +97,8 @@ static void libqb_log_fn(const char *file_name,
int main(int argc, char * argv[])
{
+ qb_loop_signal_handle sh;
+
qb_util_set_log_function(libqb_log_fn);
l = qb_loop_create();
@@ -97,6 +114,10 @@ int main(int argc, char * argv[])
qb_loop_poll_add(l, QB_LOOP_LOW, 0, POLLIN | POLLPRI | POLLNVAL,
NULL, read_stdin);
+ qb_loop_signal_add(l, QB_LOOP_MED, SIGINT, NULL, handle_exit_signal, &sh);
+ qb_loop_signal_add(l, QB_LOOP_MED, SIGSEGV, NULL, handle_exit_signal, &sh);
+ qb_loop_signal_add(l, QB_LOOP_MED, SIGHUP, NULL, handle_reconf_signal, &sh);
+
qb_loop_run(l);
return 0;
}
--
1.7.3.1
13 years, 4 months
[topic-libqb] re-worked patch series without the hdb & list changes
by Angus Salkeld
Hi
I have re worked these patches so that there is not an unneccessaryly large
amount of namespace changes (these can be done at any time later). this
should also help in cherry picking patches between branches. The hdb
patch was very extensive!
This series makes corosync have only one pthread - the logsys thread.
Regards
Angus
13 years, 4 months
[PATCH] LOOP: prevent high cpu utilization on no load.
by Angus Salkeld
We we passing "0" timeout into poll().
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/loop.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/loop.c b/lib/loop.c
index ba61115..7f7cf74 100644
--- a/lib/loop.c
+++ b/lib/loop.c
@@ -112,7 +112,7 @@ void qb_loop_run(struct qb_loop *l)
if (l->timer_source) {
ms_timeout = qb_loop_timer_msec_duration_to_expire(l->timer_source);
} else {
- ms_timeout = 0;
+ ms_timeout = -1;
}
}
todo += l->fd_source->poll(l->fd_source, ms_timeout);
--
1.7.3.1
13 years, 4 months
API Review
by Angus Salkeld
Hi
One the the next items on the TODO list
(http://libqb.org/wiki/index.php/Todo_List)
is to review the current API. The point of this
is to avoid problems in the future once the library
is deployed. If anyone is willing to help I would
appreciate it, the more eyes the better!
My self-review is below:
-Angus
General
-------
- all "objects" must be reference counted (and with common names like
ABC_ref() ABC_unref() )
ipcs
----
- It has the only use of hdb and it's probably the one that needs this the least.
Change to a pointer and add a reference count API.
- Better naming of connection functions, maybe "qb_ipcs_conn_xyz()"
- Deal better with qb_ipcs_context_[gs]et() alloc/free and refcounting - it's a mess!
At the moment the object is allocated outside of ipcs but freed inside - yuk
One solution is to add another callback disconnected() and use this as the current
destroyed_connection() has been used, then the destroyed changes meaning to
"the connection object is now been free'ed", and the user can free the context memory.
- Support message queues?
What message queues to support if any?
loop_timer
----------
We now have much more accurate timers with timerfd_create() and it
would make sense to uiltize them better.
- Change the API to have a better resolution (milli -> micro or nano seconds)
- It would be more efficient to have repeating timers to prevent
close() + timerfd_create() + epoll_ctl()
But this would also mean we would hen need reset()/stop()/start()
Anyone have any ideas about good API for timers?
- We should also support absolute timers.
13 years, 4 months
[PATCH] Fix ./check_all
by Angus Salkeld
- Spelling error in "make distcheck"
- add check_resources.sh to EXTRA_DIST
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
check_all | 2 +-
tests/Makefile.am | 1 +
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/check_all b/check_all
index 37676d5..bf1be5d 100755
--- a/check_all
+++ b/check_all
@@ -33,5 +33,5 @@ check "ac_cv_func_timerfd_create=no ac_cv_header_sys_timerfd_h=no ac_cv_func_clo
# normal configure with distcheck
./configure
-make distchack
+make distcheck
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c44e341..d4d7864 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ loop_LDADD = -lrt $(top_builddir)/lib/libqb.la
if HAVE_CHECK
+EXTRA_DIST = check_resources.sh
TESTS = check_array check_rb check_loop check_ipc check_resources.sh
--
1.7.3.1
13 years, 4 months
[PATCH 1/4] Cleanup config defines & add a check_all script
by Angus Salkeld
Run:
./check_all
to build with and without some common configurations.
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
check_all | 37 +++++++++++++++++++++++++++++
configure.ac | 59 ++++++++++++----------------------------------
include/os_base.h | 34 +++++++++++++++++++++++++++
include/qb/qbutil.h | 9 ++++++-
lib/Makefile.am | 8 +++++-
lib/ipc_int.h | 17 +------------
lib/ipc_posix_mq.c | 2 +-
lib/loop_poll.c | 25 +++++++++----------
lib/ringbuffer_helper.c | 6 ++--
lib/util.c | 57 ++++++++++++++++++++++++++++++---------------
tests/check_loop.c | 2 +-
11 files changed, 159 insertions(+), 97 deletions(-)
create mode 100755 check_all
diff --git a/check_all b/check_all
new file mode 100755
index 0000000..37676d5
--- /dev/null
+++ b/check_all
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+./autogen.sh
+
+
+check () {
+ echo "$1"
+ ( ./configure $1 --enable-fatal-warnings )
+ make check
+ if [ $? -ne 0 ]
+ then
+ echo "======================"
+ echo failed: $1
+ echo "======================"
+ exit 1
+ fi
+}
+
+# use sys-v semaphores
+check "CFLAGS=-DDISABLE_POSIX_THREAD_PROCESS_SHARED"
+
+# no timerfd
+check "ac_cv_func_timerfd_create=no ac_cv_header_sys_timerfd_h=no"
+
+# no clock_gettime
+check "ac_cv_func_clock_gettime=no"
+
+# no epoll
+check "ac_cv_func_epoll_create1=no ac_cv_func_epoll_create=no"
+
+# bsd-like
+check "ac_cv_func_timerfd_create=no ac_cv_header_sys_timerfd_h=no ac_cv_func_clock_gettime=no ac_cv_func_epoll_create1=no ac_cv_func_epoll_create=no"
+
+# normal configure with distcheck
+./configure
+make distchack
+
diff --git a/configure.ac b/configure.ac
index c76aabc..0003c33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,7 +111,7 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h netinet/in.h stdint.h \
time.h sys/time.h stdlib.h string.h strings.h sys/types.h sys/stat.h \
- sys/param.h sys/socket.h sys/time.h sys/timerfd.h \
+ sys/param.h sys/socket.h sys/time.h sys/timerfd.h sys/epoll.h \
sys/sockio.h sys/un.h syslog.h errno.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
@@ -129,7 +129,6 @@ AC_TYPE_UINT64_T
# Checks for library functions.
AC_FUNC_CHOWN
-AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_FUNC_MMAP
@@ -139,6 +138,16 @@ AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday memset munmap \
socket strchr strerror strstr epoll_create epoll_create1 \
pthread_spin_lock timerfd_create])
+## local defines
+PACKAGE_FEATURES=""
+
+if test $ac_cv_func_timerfd_create = yes; then
+ PACKAGE_FEATURES="$PACKAGE_FEATURES timerfd"
+fi
+if test $ac_cv_func_epoll_create = yes; then
+ PACKAGE_FEATURES="$PACKAGE_FEATURES epoll"
+fi
+
# Check for atomic support
gcc_has_builtin_atomic_operations=no
if test x"$GCC" = xyes; then
@@ -155,6 +164,7 @@ if test x"$GCC" = xyes; then
AC_MSG_RESULT($gcc_has_builtin_atomic_operations)
if test $gcc_has_builtin_atomic_operations = yes; then
memory_barrier_needed=yes
+ PACKAGE_FEATURES="$PACKAGE_FEATURES gcc__sync"
else
case $host_cpu in
sparc*)
@@ -198,19 +208,10 @@ AM_CONDITIONAL(HAVE_GCC_BUILTINS_FOR_ATOMIC_OPERATIONS,
[test $gcc_has_builtin_atomic_operations = yes])
-## local defines
-PACKAGE_FEATURES=""
-
LINT_FLAGS="-weak -unrecog +posixlib +ignoresigns -fcnuse \
-badflag -D__gnuc_va_list=va_list -D__attribute\(x\)= \
-warnposix +matchanyintegral"
-# libraries SONAME
-SOMAJOR="0"
-SOMINOR="1"
-SOMICRO="0"
-SONAME="${SOMAJOR}.${SOMINOR}.${SOMICRO}"
-
# local options
AC_ARG_ENABLE([ansi],
[ --enable-ansi : force to build with ANSI standards. ],
@@ -228,11 +229,6 @@ AC_ARG_ENABLE([coverage],
[ --enable-coverage : coverage analysis of the codebase. ],
[ default="no" ])
-AC_ARG_ENABLE([timerfd],
- [ --enable-timerfd : use timerfd timers. ],
- [ enable_timerfd=$enableval ],
- [ enable_timerfd="auto" ])
-
AC_ARG_WITH([socket-dir],
[ --with-socket-dir=DIR : socket dir. ],
[ SOCKETDIR="$withval" ],
@@ -245,7 +241,7 @@ case "$host_os" in
*linux*)
AC_DEFINE_UNQUOTED([QB_LINUX], [1],
[Compiling for Linux platform])
- LINT_FLAGS+=" -expect 22"
+ LINT_FLAGS+=" -expect 21"
;;
darwin*)
AC_DEFINE_UNQUOTED([QB_DARWIN], [1],
@@ -257,6 +253,8 @@ case "$host_os" in
[Number of chars in a path name including nul])
AC_DEFINE_UNQUOTED([NAME_MAX], [255],
[Number of chars in a file name])
+ AC_DEFINE_UNQUOTED([DISABLE_POSIX_THREAD_PROCESS_SHARED], [1],
+ [Disable _POSIX_THREAD_PROCESS_SHARED])
;;
*bsd*)
AC_DEFINE_UNQUOTED([QB_BSD], [1],
@@ -354,26 +352,7 @@ else
COVERAGE_LDFLAGS=""
fi
-# --- timerfd ---
-use_timerfd=no
-if test "x${enable_timerfd}" = xauto ; then
- if test "x${ac_cv_func_timerfd_create}" = xyes ; then
- use_timerfd=yes
- fi
-fi
-if test "x${enable_timerfd}" = xyes ; then
- if test "x${ac_cv_func_timerfd_create}" = xyes ; then
- use_timerfd=yes
- else
- AC_MSG_ERROR([Asked for timerfd but none available])
- fi
-fi
-if test "x$use_timerfd" = xyes ; then
- AC_MSG_NOTICE([Enabling timerfd timers])
- AC_DEFINE_UNQUOTED([USE_TIMERFD], 1, [use timerfd timers])
- PACKAGE_FEATURES="$PACKAGE_FEATURES timerfd"
-fi
-AM_CONDITIONAL(USE_TIMERFD, [test "x$use_timerfd" = xyes])
+AM_CONDITIONAL(USE_TIMERFD, [test "x$ac_cv_func_timerfd_create" = xyes])
# --- ansi ---
if test "x${enable_ansi}" = xyes && \
@@ -403,11 +382,6 @@ LDFLAGS="$ENV_LDFLAGS $COVERAGE_LDFLAGS"
# substitute what we need:
AC_SUBST([SOCKETDIR])
-AC_SUBST([SOMAJOR])
-AC_SUBST([SOMINOR])
-AC_SUBST([SOMICRO])
-AC_SUBST([SONAME])
-
AC_SUBST([LINT_FLAGS])
AC_DEFINE_UNQUOTED([SOCKETDIR], "$(eval echo ${SOCKETDIR})", [Socket directory])
@@ -442,7 +416,6 @@ AC_MSG_RESULT([ SOCKETDIR = ${SOCKETDIR}])
AC_MSG_RESULT([ Features =${PACKAGE_FEATURES}])
AC_MSG_RESULT([])
AC_MSG_RESULT([$PACKAGE build info:])
-AC_MSG_RESULT([ Library SONAME = ${SONAME}])
AC_MSG_RESULT([ Default optimization = ${OPT_CFLAGS}])
AC_MSG_RESULT([ Default debug options = ${GDB_CFLAGS}])
AC_MSG_RESULT([ Extra compiler warnings = ${EXTRA_WARNING}])
diff --git a/include/os_base.h b/include/os_base.h
index 6123289..decf375 100644
--- a/include/os_base.h
+++ b/include/os_base.h
@@ -43,6 +43,10 @@
#include <stdint.h>
#endif /* HAVE_STDINT_H */
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
#include <assert.h>
#ifdef HAVE_STDLIB_H
@@ -93,4 +97,34 @@
#endif /* HAVE_SYSLOG_H */
#endif /* S_SPLINT_S */
+#if defined HAVE_CLOCK_GETTIME && defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+#define HAVE_MONOTONIC_CLOCK 1
+#endif /* have monotonic clock */
+
+#ifdef HAVE_TIMERFD_CREATE
+#define HAVE_TIMERFD 1
+#endif /* HAVE_TIMERFD_CREATE */
+
+#ifdef HAVE_EPOLL_CREATE1
+#define HAVE_EPOLL 1
+#endif /* HAVE_EPOLL_CREATE */
+
+/*
+ * Darwin claims to support process shared synchronization
+ * but it really does not. The unistd.h header file is wrong.
+ */
+#if defined(DISABLE_POSIX_THREAD_PROCESS_SHARED) || defined(__UCLIBC__)
+#undef HAVE_POSIX_SHARED_SEMAPHORE
+#undef HAVE_PTHREAD_SHARED_SPIN_LOCK
+#else
+#if _POSIX_THREAD_PROCESS_SHARED > 0
+#define HAVE_POSIX_SHARED_SEMAPHORE 1
+
+#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#define HAVE_PTHREAD_SHARED_SPIN_LOCK 1
+#endif /* HAVE_PTHREAD_SPIN_LOCK */
+
+#endif /* _POSIX_THREAD_PROCESS_SHARED */
+#endif /* DISABLE_POSIX_THREAD_PROCESS_SHARED */
+
#endif /* QB_OS_BASE_H_DEFINED */
diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h
index 58420bc..39ca68f 100644
--- a/include/qb/qbutil.h
+++ b/include/qb/qbutil.h
@@ -96,7 +96,7 @@ void qb_util_set_log_function(qb_util_log_fn_t fn);
void qb_timespec_add_ms(struct timespec *ts, int32_t ms);
/**
- * Get the current number of nanao secounds produced
+ * Get the current number of nano secounds produced
* by the systems incrementing clock (CLOCK_MONOTOMIC
* if available).
*/
@@ -113,6 +113,13 @@ uint64_t qb_util_nano_monotonic_hz(void);
*/
uint64_t qb_util_nano_from_epoch_get(void);
+/**
+ * Get the time in timespec since epoch.
+ * @param ts (out) the timespec
+ * @return status (0 == ok, -errno on error)
+ */
+void qb_util_timespec_from_epoch_get(struct timespec *ts);
+
/* *INDENT-OFF* */
#ifdef __cplusplus
}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 1e99976..e2f305f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -63,8 +63,14 @@ ALL_LINT_FLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(LINT_FLAGS)
run_splint.sh: $(top_srcdir)/configure.ac
- echo "$(SPLINT) $(ALL_LINT_FLAGS) $(source_to_lint)" > $@
+ echo "$(SPLINT) $(ALL_LINT_FLAGS) $(addprefix $(top_srcdir)/lib/, $(source_to_lint))" > $@
chmod +x $@
+
+dist-clean-local:
+ rm -f run_splint.sh
+
+clean-generic:
+ rm -f run_splint.sh
endif
diff --git a/lib/ipc_int.h b/lib/ipc_int.h
index 24bfc2a..4d607e8 100644
--- a/lib/ipc_int.h
+++ b/lib/ipc_int.h
@@ -33,22 +33,9 @@
#include <qb/qbipc_common.h>
#include <qb/qbrb.h>
-/*
- * Darwin claims to support process shared synchronization
- * but it really does not. The unistd.h header file is wrong.
- */
-#if defined(QB_DARWIN) || defined(__UCLIBC__)
-#undef _POSIX_THREAD_PROCESS_SHARED
-#define _POSIX_THREAD_PROCESS_SHARED -1
-#endif
-
-#ifndef _POSIX_THREAD_PROCESS_SHARED
-#define _POSIX_THREAD_PROCESS_SHARED -1
-#endif
-
-#if _POSIX_THREAD_PROCESS_SHARED > 0
+#ifdef HAVE_POSIX_SHARED_SEMAPHORE
#include <semaphore.h>
-#endif
+#endif /* HAVE_POSIX_SHARED_SEMAPHORE */
/*
Client Server
diff --git a/lib/ipc_posix_mq.c b/lib/ipc_posix_mq.c
index 2fd5868..48df755 100644
--- a/lib/ipc_posix_mq.c
+++ b/lib/ipc_posix_mq.c
@@ -192,7 +192,7 @@ static ssize_t qb_ipc_pmq_recv(struct qb_ipc_one_way *one_way,
ssize_t res;
if (ms_timeout >= 0) {
- clock_gettime(CLOCK_REALTIME, &ts_timeout);
+ qb_util_timespec_from_epoch_get(&ts_timeout);
qb_timespec_add_ms(&ts_timeout, ms_timeout);
}
diff --git a/lib/loop_poll.c b/lib/loop_poll.c
index 3583679..2067f9c 100644
--- a/lib/loop_poll.c
+++ b/lib/loop_poll.c
@@ -21,10 +21,9 @@
#include "os_base.h"
#include <sys/resource.h>
-#ifdef HAVE_EPOLL_CREATE1
+#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
-#define HAVE_EPOLL 1
-#endif /* HAVE_EPOLL_CREATE */
+#endif /* HAVE_SYS_EPOLL_H */
#include <sys/poll.h>
#ifndef S_SPLINT_S
#ifdef HAVE_SYS_TIMERFD_H
@@ -227,7 +226,7 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
poll_fds_usage_check(s);
for (i = 0; i < s->poll_entry_count; i++) {
- assert(qb_array_index(l->fd_source->poll_entries, i, (void**)&pe) == 0);
+ assert(qb_array_index(s->poll_entries, i, (void**)&pe) == 0);
memcpy(&s->ufds[i], &pe->ufd, sizeof(struct pollfd));
}
@@ -244,7 +243,7 @@ static int32_t poll_and_add_to_jobs(struct qb_loop_source* src, int32_t ms_timeo
// empty
continue;
}
- assert(qb_array_index(l->fd_source->poll_entries, i, (void**)&pe) == 0);
+ assert(qb_array_index(s->poll_entries, i, (void**)&pe) == 0);
if (s->ufds[i].revents == pe->ufd.revents) {
// entry already in the job queue.
continue;
@@ -370,8 +369,6 @@ static int32_t _poll_add_(struct qb_loop *l,
struct qb_poll_source * s;
#ifdef HAVE_EPOLL
struct epoll_event *ev;
-#else
- struct pollfd *ufds;
#endif /* HAVE_EPOLL */
if (l == NULL) {
@@ -412,7 +409,7 @@ int32_t qb_loop_poll_add(struct qb_loop *l,
void *data,
qb_loop_poll_dispatch_fn dispatch_fn)
{
- struct qb_poll_entry *pe;
+ struct qb_poll_entry *pe = NULL;
int32_t res = _poll_add_(l, p, fd, events, data, &pe);
pe->poll_dispatch_fn = dispatch_fn;
pe->type = QB_POLL;
@@ -495,7 +492,7 @@ int32_t qb_loop_poll_del(struct qb_loop *l, int32_t fd)
return -EBADF;
}
-#ifdef USE_TIMERFD
+#ifdef HAVE_TIMERFD
int32_t qb_loop_timer_msec_duration_to_expire(struct qb_loop_source *timer_source)
{
return 0;
@@ -573,7 +570,9 @@ int32_t qb_loop_timer_del(struct qb_loop *l, qb_loop_timer_handle th)
{
struct qb_poll_entry *pe;
struct qb_poll_source *s;
+#ifdef HAVE_EPOLL
int32_t res;
+#endif /* HAVE_EPOLL */
if (l == NULL || th == NULL) {
return -EINVAL;
@@ -593,9 +592,9 @@ int32_t qb_loop_timer_del(struct qb_loop *l, qb_loop_timer_handle th)
return res;
}
#else
- s->ufds[i].fd = -1;
- s->ufds[i].events = 0;
- s->ufds[i].revents = 0;
+ s->ufds[pe->install_pos].fd = -1;
+ s->ufds[pe->install_pos].events = 0;
+ s->ufds[pe->install_pos].revents = 0;
#endif /* HAVE_EPOLL */
close(pe->ufd.fd);
@@ -623,5 +622,5 @@ uint64_t qb_loop_timer_expire_time_get(struct qb_loop *l, qb_loop_timer_handle t
return (its.it_value.tv_sec * QB_TIME_NS_IN_SEC) + its.it_value.tv_nsec;
}
-#endif /* USE_TIMERFD */
+#endif /* HAVE_TIMERFD */
diff --git a/lib/ringbuffer_helper.c b/lib/ringbuffer_helper.c
index 08548ab..9d96f13 100644
--- a/lib/ringbuffer_helper.c
+++ b/lib/ringbuffer_helper.c
@@ -27,7 +27,7 @@ static int32_t my_posix_sem_timedwait(qb_ringbuffer_t * rb, int32_t ms_timeout)
int32_t res;
if (ms_timeout > 0) {
- clock_gettime(CLOCK_REALTIME, &ts_timeout);
+ qb_util_timespec_from_epoch_get(&ts_timeout);
qb_timespec_add_ms(&ts_timeout, ms_timeout);
}
@@ -250,9 +250,9 @@ static int32_t my_sysv_sem_create(qb_ringbuffer_t * rb, uint32_t flags)
int32_t qb_rb_sem_create(struct qb_ringbuffer_s * rb, uint32_t flags)
{
int32_t can_use_shared_posix = QB_FALSE;
-#if _POSIX_THREAD_PROCESS_SHARED > 0
+#ifdef HAVE_POSIX_SHARED_SEMAPHORE
can_use_shared_posix = QB_TRUE;
-#endif
+#endif /* HAVE_POSIX_SHARED_SEMAPHORE */
if (!can_use_shared_posix && (rb->flags & QB_RB_FLAG_SHARED_PROCESS)) {
rb->sem_timedwait_fn = my_sysv_sem_timedwait;
rb->sem_post_fn = my_sysv_sem_post;
diff --git a/lib/util.c b/lib/util.c
index ed39c2e..336b4a9 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -24,20 +24,15 @@
#include <sys/shm.h>
#include <sys/mman.h>
#include <pthread.h>
-#if _POSIX_THREAD_PROCESS_SHARED > 0
-#include <semaphore.h>
-#else
-#include <sys/sem.h>
-#endif
#include <sys/stat.h>
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
struct qb_thread_lock_s {
qb_thread_lock_type_t type;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
pthread_spinlock_t spinlock;
-#endif
+#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
pthread_mutex_t mutex;
};
@@ -46,14 +41,12 @@ qb_thread_lock_t *qb_thread_lock_create(qb_thread_lock_type_t type)
struct qb_thread_lock_s *tl = malloc(sizeof(struct qb_thread_lock_s));
int32_t res;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
-#if _POSIX_THREAD_PROCESS_SHARED > 0
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
if (type == QB_THREAD_LOCK_SHORT) {
tl->type = QB_THREAD_LOCK_SHORT;
res = pthread_spin_init(&tl->spinlock, 1);
} else
-#endif
-#endif
+#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
{
tl->type = QB_THREAD_LOCK_LONG;
res = pthread_mutex_init(&tl->mutex, NULL);
@@ -69,11 +62,11 @@ qb_thread_lock_t *qb_thread_lock_create(qb_thread_lock_type_t type)
int32_t qb_thread_lock(qb_thread_lock_t * tl)
{
int32_t res;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
if (tl->type == QB_THREAD_LOCK_SHORT) {
res = -pthread_spin_lock(&tl->spinlock);
} else
-#endif
+#endif /* HAVE_PTHREAD_SHARED_SPIN_LOCK */
{
res = -pthread_mutex_lock(&tl->mutex);
}
@@ -83,7 +76,7 @@ int32_t qb_thread_lock(qb_thread_lock_t * tl)
int32_t qb_thread_unlock(qb_thread_lock_t * tl)
{
int32_t res;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
if (tl->type == QB_THREAD_LOCK_SHORT) {
res = -pthread_spin_unlock(&tl->spinlock);
} else
@@ -97,7 +90,7 @@ int32_t qb_thread_unlock(qb_thread_lock_t * tl)
int32_t qb_thread_trylock(qb_thread_lock_t * tl)
{
int32_t res;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
if (tl->type == QB_THREAD_LOCK_SHORT) {
res = -pthread_spin_trylock(&tl->spinlock);
} else
@@ -111,7 +104,7 @@ int32_t qb_thread_trylock(qb_thread_lock_t * tl)
int32_t qb_thread_lock_destroy(qb_thread_lock_t * tl)
{
int32_t res;
-#if defined(HAVE_PTHREAD_SPIN_LOCK)
+#ifdef HAVE_PTHREAD_SHARED_SPIN_LOCK
if (tl->type == QB_THREAD_LOCK_SHORT) {
res = -pthread_spin_destroy(&tl->spinlock);
} else
@@ -156,7 +149,7 @@ void qb_timespec_add_ms(struct timespec *ts, int32_t ms)
#endif /* S_SPLINT_S */
}
-#if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+#ifdef HAVE_MONOTONIC_CLOCK
uint64_t qb_util_nano_current_get(void)
{
uint64_t nano_monotonic;
@@ -168,6 +161,17 @@ uint64_t qb_util_nano_current_get(void)
(ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t)ts.tv_nsec;
return (nano_monotonic);
}
+uint64_t qb_util_nano_from_epoch_get(void)
+{
+ uint64_t nano_monotonic;
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ nano_monotonic =
+ (ts.tv_sec * QB_TIME_NS_IN_SEC) + (uint64_t)ts.tv_nsec;
+ return (nano_monotonic);
+}
uint64_t qb_util_nano_monotonic_hz(void)
{
@@ -182,8 +186,12 @@ uint64_t qb_util_nano_monotonic_hz(void)
return (nano_monotonic_hz);
}
+
+void qb_util_timespec_from_epoch_get(struct timespec *ts)
+{
+ clock_gettime(CLOCK_REALTIME, ts);
+}
#else
-#warning "Your system doesn't support monotonic timer. gettimeofday will be used"
uint64_t qb_util_nano_current_get(void)
{
return qb_util_nano_from_epoch_get();
@@ -193,7 +201,17 @@ uint64_t qb_util_nano_monotonic_hz(void)
{
return HZ;
}
-#endif
+
+void qb_util_timespec_from_epoch_get(struct timespec *ts)
+{
+ struct timeval time_from_epoch;
+ gettimeofday(&time_from_epoch, 0);
+
+#ifndef S_SPLINT_S
+ ts->tv_sec = time_from_epoch.tv_sec;
+ ts->tv_nsec = time_from_epoch.tv_usec * QB_TIME_NS_IN_USEC;
+#endif /* S_SPLINT_S */
+}
uint64_t qb_util_nano_from_epoch_get(void)
{
@@ -206,6 +224,7 @@ uint64_t qb_util_nano_from_epoch_get(void)
return (nano_from_epoch);
}
+#endif
void qb_util_set_log_function(qb_util_log_fn_t fn)
{
diff --git a/tests/check_loop.c b/tests/check_loop.c
index 36c1645..0f82b30 100644
--- a/tests/check_loop.c
+++ b/tests/check_loop.c
@@ -222,7 +222,7 @@ static void stop_watch_tmo(void*data)
qb_loop_timer_add(sw->l, QB_LOOP_LOW, sw->ms_timer, data, stop_watch_tmo, &th);
} else {
per = (sw->total / sw->count) * 100 / (sw->ms_timer * QB_TIME_NS_IN_MSEC);
- printf("average error for %d ms timer is %lld (ns) (%lld%%)\n",
+ printf("average error for %d ms timer is %"PRIi64" (ns) (%"PRIi64"%%)\n",
sw->ms_timer,
sw->total/sw->count, per);
if (sw->ms_timer == 100) {
--
1.7.2.3
13 years, 5 months