osaf/libs/core/common/Makefile.am | 2 + osaf/libs/core/common/include/osaf_poll.h | 97 +++++++ osaf/libs/core/common/include/osaf_time.h | 371 ++++++++++++++++++++++++++++++ osaf/libs/core/common/osaf_poll.c | 130 ++++++++++ osaf/libs/core/common/osaf_time.c | 52 ++++ 5 files changed, 652 insertions(+), 0 deletions(-)
Add new utility and convenience APIs, declared in osaf_poll.h and osaf_time.h, respectively. osaf_poll.h contains utility functions that work in a similar way as the Linux function poll() and ppoll(), except that they handle errors themselves instead of returning -1. The errno value EINTR is handled with a loop, and the functions keep track of time so that the time-out will happen at the same time no matter if the functions were interrupted by a signal or not. Other errno values will cause the process to be aborted, since they indicate the presence of a software bug and the program cannot continue in a safe way. osaf_time.h contains utility functions for reading the time and sleeping, that work in a similar way as the Linux functions clock_gettime() and nanosleep(), except that they abort the process instead of returning -1. There are also utilty functions for manipulating "struct timespec" times. struct timespec is used for representing a time in many POSIX functions, and the reason for having a structure is that a 64-bit integer is not sufficient for representing the full time. diff --git a/osaf/libs/core/common/Makefile.am b/osaf/libs/core/common/Makefile.am --- a/osaf/libs/core/common/Makefile.am +++ b/osaf/libs/core/common/Makefile.am @@ -32,6 +32,8 @@ libopensaf_common_la_SOURCES = \ ncs_sprr.c \ logtrace.c \ osaf_utility.c \ + osaf_poll.c \ + osaf_time.c \ nid_start_util.c \ saf_edu.c \ daemon.c \ diff --git a/osaf/libs/core/common/include/osaf_poll.h b/osaf/libs/core/common/include/osaf_poll.h new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/include/osaf_poll.h @@ -0,0 +1,97 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2013 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +/** @file + * + * This file contains an OpenSAF replacement of the POSIX function poll(). The + * definitions in this file are for internal use within OpenSAF only. + */ + +#ifndef OPENSAF_BASE_OSAF_POLL_H_ +#define OPENSAF_BASE_OSAF_POLL_H_ + +#include <poll.h> +#include <time.h> +#include <signal.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Wait for events on file descriptors + * + * This is a convenience function that behaves exactly like the POSIX function + * poll(3P), except that it will abort the process instead of returning an error + * code in case of a failure. It handles the EINTR case internally with a loop, + * and ensures that the function will time out at the same time no matter if the + * system call was interrupted by a signal or not. + * + * The return value will always be in the range [0, i_nfds]. + */ +extern unsigned osaf_poll(struct pollfd* io_fds, nfds_t i_nfds, int i_timeout); + +/** + * @brief Wait for events on file descriptors + * + * This is a convenience function that behaves exactly like the Linux function + * ppoll(3), except that it will abort the process instead of returning an error + * code in case of a failure. It handles the EINTR case internally with a loop, + * and ensures that the function will time out at the same time no matter if the + * system call was interrupted by a signal or not. Note that since the ppoll() + * function is currently not included in LSB, this function is implemented + * internally using poll(). Therefore, the @a i_sigmask parameter is not + * supported and must be set to NULL. + * + * The return value will always be in the range [0, i_nfds]. + */ +extern unsigned osaf_ppoll(struct pollfd* io_fds, nfds_t i_nfds, + const struct timespec* i_timeout_ts, const sigset_t* i_sigmask); + +/** + * @brief Wait for events on a file descriptor + * + * This is a convenience function that behaves exactly like the POSIX function + * poll(3P), except that it only supports waiting for read events on one single + * file descriptor passed as the parameter @a i_fd. Also, it will abort the + * process instead of returning an error code in case the poll() function + * fails. It handles the EINTR case internally with a loop, and ensures that the + * function will time out at the same time no matter if the system call was + * interrupted by a signal or not. + * + * Since there is no struct pollfd* parameter, this convenience function has a + * different way of reporting what events were received on the file descriptor + * @a i_fd. It will return 1 if there was a POLLIN event on the file descriptor + * (just like poll() does). But if poll() returned an error event for the file + * descriptor @a i_fd, this function will handle the there different cases as + * follows: + * + * POLLNVAL - in this case the process will be aborted. + * + * POLLERR - errno will be set to EIO and -1 will be returned. + * + * POLLHUP - errno will be set to EPIPE and -1 will be returned. + * + * The return value from this function will always be in the range [-1, 1]. + */ +extern int osaf_poll_one_fd(int i_fd, int i_timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENSAF_BASE_OSAF_POLL_H_ */ diff --git a/osaf/libs/core/common/include/osaf_time.h b/osaf/libs/core/common/include/osaf_time.h new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/include/osaf_time.h @@ -0,0 +1,371 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2013 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +/** @file + * + * This file contains utility functions related to time and time conversion. + * Many functions operate on timespec structures, and require that the structure + * is normalized. By this is meant that the tv_nsec member of the structure has + * a value in the range [0, 999999999]. The osaf_normalize_timespec() function + * can be used to convert a timespec strucure to normalized form, when + * necessary. Negative times are not supported. + * + * The definitions in this file are for internal use within OpenSAF only. For + * performace reasons, which may be important e.g. when doing time measurements, + * all functions are declared as inline. + */ + +#ifndef OPENSAF_BASE_OSAF_TIME_H_ +#define OPENSAF_BASE_OSAF_TIME_H_ + +#include <stdint.h> +#include <time.h> +#include <sys/time.h> +#include "osaf_utility.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /** + * Number of nanoseconds per second. + */ + kNanosPerSec = 1000000000, + /** + * Number of milliseconds per second. + */ + kMicrosPerSec = 1000000, + /** + * Number of microseconds per second. + */ + kMillisPerSec = 1000 +}; + +/** + * @brief Sleep for the specified time + * + * This is a convenience function that behaves exactly like the POSIX function + * nanosleep(3P), except that it will abort the process instead of returning an + * error code in case of a failure. In case the thread was interrupted by a + * signal, nanosleep() will be called again to sleep the remaining time. + */ +extern void osaf_nanosleep(const struct timespec* i_req); + +/** + * @brief Get the time + * + * This is a convenience function that behaves exactly like the POSIX function + * clock_gettime(3P), except that it will abort the process instead of returning + * an error code in case of a failure. + */ +static inline void osaf_clock_gettime(clockid_t i_clk_id, + struct timespec* o_ts); + +/** + * @brief Normalize a timespec structure. + * + * This function normalizes the timespec structure @a i_ts and stores the result + * in the output parameter @a o_nrm. The tv_nsec member of the normalized + * structure is guaranteed to be in the range [0, 999999999]. The parameters are + * allowed to point to the same memory address. + */ +static inline void osaf_normalize_timespec(const struct timespec* i_ts, + struct timespec* o_nrm); + +/** + * @brief Calculate the sum of two timespec structures. + * + * This function adds the two timespec structures @a i_time1 and @a i_time2, and + * stores the result in the output parameter @a o_sum. The input parameters @a + * i_time1 and @a i_time2 must be normalized, and the output parameter @a o_sum + * is guaranteed to also be normalized. The parameters are allowed to point to + * the same memory address. Negative times are not supported. + */ +static inline void osaf_timespec_add(const struct timespec* i_time1, + const struct timespec* i_time2, + struct timespec* o_sum); + +/** + * @brief Calculate the difference between two timespec structures. + * + * This function subtracts the timespec structure @a i_start from the timespec + * structure @a i_end, and stores the result in the output parameter @a + * o_difference. The input parameters @a i_end and @a i_start must be + * normalized, and the output parameter @a o_difference is guaranteed to also be + * normalized. The parameters are allowed to point to the same memory + * address. Negative times are not supported. + */ +static inline void osaf_timespec_subtract(const struct timespec* i_end, + const struct timespec* i_start, + struct timespec* o_difference); + +/** + * @brief Compare two timespec structures. + * + * This function compares the two timespec structures @a i_end and @a i_start. + * The return value will be -1, 0 or 1, if @a i_end is less than, equal to, or + * greater than @a i_start, respectively. The input parameters @a i_end and @a + * i_start must be normalized. + */ +static inline int osaf_timespec_compare(const struct timespec* i_end, + const struct timespec* i_start); + +/** + * @brief Convert a timespec structure to a timeval structure. + * + * This function converts the timespec structure @a i_ts to a timeval structure, + * and stores the result in the output parameter @a o_tv. The input parameter @a + * i_ts does not have to be normalized. The output parameter @a o_tv will be + * normalized if the input parameter @a i_ts was normalized. The parameters are + * allowed to point to the same memory address. + */ +static inline void osaf_timespec_to_timeval(const struct timespec* i_ts, + struct timeval* o_tv); + +/** + * @brief Convert a timeval structure to a timespec structure. + * + * This function converts the timeval structure @a i_tv to a timespec structure, + * and stores the result in the output parameter @a o_ts. The input parameter @a + * i_tv does not have to be normalized. The output parameter @a o_ts will be + * normalized if the input parameter @a i_tv was normalized. The parameters are + * allowed to point to the same memory address. + */ +static inline void osaf_timeval_to_timespec(const struct timeval* i_tv, + struct timespec* o_ts); + +/** + * @brief Convert an integer representing time in milliseconds to a timespec + * structure. + * + * This function converts the integer @a i_millis to a timespec structure, and + * stores the result in the output parameter @a o_ts. The unit of @a i_millis is + * milliseconds. The output parameter @a o_ts is guaranteed to be normalized. + */ +static inline void osaf_millis_to_timespec(uint64_t i_millis, + struct timespec* o_ts); + +/** + * @brief Convert an integer representing time in microseconds to a timespec + * structure. + * + * This function converts the integer @a i_micros to a timespec structure, and + * stores the result in the output parameter @a o_ts. The unit of @a i_micros is + * microseconds. The output parameter @a o_ts is guaranteed to be normalized. + */ +static inline void osaf_micros_to_timespec(uint64_t i_micros, + struct timespec* o_ts); + +/** + * @brief Convert a double representing time in seconds to a timespec structure. + * + * This function converts the double precision floating point number @a + * i_seconds to a timespec structure, and stores the result in the output + * parameter @a o_ts. The unit of @a i_seconds is microseconds. The output + * parameter @a o_ts is guaranteed to be normalized. + */ +static inline void osaf_double_to_timespec(double i_seconds, + struct timespec* o_ts); + +/** + * @brief Convert an integer representing time in nanoseconds to a timespec + * structure. + * + * This function converts the integer @a i_nanos to a timespec structure, and + * stores the result in the output parameter @a o_ts. The unit of @a i_nanos is + * nanoseconds. The output parameter @a o_ts is guaranteed to be normalized. + */ +static inline void osaf_nanos_to_timespec(uint64_t i_nanos, + struct timespec* o_ts); + +/** + * @brief Convert a timespec structure to an integer representing time + * in milliseconds. + * + * This function converts the timespec structure @a i_ts to an integer + * representing time in milliseconds. The result will be rounded down. Note that + * the returned unsigned 64-bit integer has a smaller range than the range than + * what is possible to represent in a timespec structure. + */ +static inline uint64_t osaf_timespec_to_millis(const struct timespec* i_ts); + +/** + * @brief Convert a timespec structure to an integer representing time + * in microseconds. + * + * This function converts the timespec structure @a i_ts to an integer + * representing time in microseconds. The result will be rounded down. Note that + * the returned unsigned 64-bit integer has a smaller range than the range than + * what is possible to represent in a timespec structure. + */ +static inline uint64_t osaf_timespec_to_micros(const struct timespec* i_ts); + +/** + * @brief Convert a timespec structure to an integer representing time + * in nanoseconds. + * + * This function converts the timespec structure @a i_ts to an integer + * representing time in nanoseconds. Note that the returned unsigned 64-bit + * integer has a smaller range than the range than what is possible to represent + * in a timespec structure. + */ +static inline uint64_t osaf_timespec_to_nanos(const struct timespec* i_ts); + +/** + * @brief Convert a timespec structure to a double representing time in + * seconds. + * + * This function converts the timespec structure @a i_ts to a double precision + * floating point number. The input parameter @a i_ts does not have to be + * normalized. The unit of the returned value is seconds. Note you will lose + * precision when converting to a double. + */ +static inline double osaf_timespec_to_double(const struct timespec* i_ts); + +static inline void osaf_clock_gettime(clockid_t i_clk_id, struct timespec* o_ts) +{ + if (clock_gettime(i_clk_id, o_ts) != 0) osaf_abort(i_clk_id); +} + +static inline void osaf_normalize_timespec(const struct timespec* i_ts, + struct timespec* o_nrm) +{ + time_t sec = i_ts->tv_sec + i_ts->tv_nsec / kNanosPerSec; + long nsec = i_ts->tv_nsec % kNanosPerSec; + if (nsec < 0) { + sec -= 1; + nsec += kNanosPerSec; + } + o_nrm->tv_sec = sec; + o_nrm->tv_nsec = nsec; +} + +static inline void osaf_timespec_add(const struct timespec* i_time1, + const struct timespec* i_time2, + struct timespec* o_sum) +{ + time_t sec = i_time1->tv_sec + i_time2->tv_sec; + long nsec = i_time1->tv_nsec + i_time2->tv_nsec; + if (nsec >= kNanosPerSec) { + sec += 1; + nsec -= kNanosPerSec; + } + o_sum->tv_sec = sec; + o_sum->tv_nsec = nsec; +} + +static inline void osaf_timespec_subtract(const struct timespec* i_end, + const struct timespec* i_start, + struct timespec* o_difference) +{ + time_t sec = i_end->tv_sec - i_start->tv_sec; + long nsec = i_end->tv_nsec - i_start->tv_nsec; + if (nsec < 0) { + sec -= 1; + nsec += kNanosPerSec; + } + o_difference->tv_sec = sec; + o_difference->tv_nsec = nsec; +} + +static inline int osaf_timespec_compare(const struct timespec* i_end, + const struct timespec* i_start) +{ + if (i_end->tv_sec == i_start->tv_sec) { + if (i_end->tv_nsec < i_start->tv_nsec) return -1; + return i_end->tv_nsec != i_start->tv_nsec ? 1 : 0; + } + return i_end->tv_sec > i_start->tv_sec ? 1 : -1; +} + +static inline void osaf_timespec_to_timeval(const struct timespec* i_ts, + struct timeval* o_tv) +{ + time_t sec = i_ts->tv_sec; + suseconds_t usec = i_ts->tv_nsec / (kMicrosPerSec / kMillisPerSec); + o_tv->tv_sec = sec; + o_tv->tv_usec = usec; +} + +static inline void osaf_timeval_to_timespec(const struct timeval* i_tv, + struct timespec* o_ts) +{ + time_t sec = i_tv->tv_sec; + long nsec = ((long) i_tv->tv_usec) * (kMicrosPerSec / kMillisPerSec); + o_ts->tv_sec = sec; + o_ts->tv_nsec = nsec; +} + +static inline void osaf_millis_to_timespec(uint64_t i_millis, + struct timespec* o_ts) +{ + o_ts->tv_sec = i_millis / kMillisPerSec; + o_ts->tv_nsec = (i_millis % kMillisPerSec) * (kNanosPerSec / + kMillisPerSec); +} + +static inline void osaf_micros_to_timespec(uint64_t i_micros, + struct timespec* o_ts) +{ + o_ts->tv_sec = i_micros / kMicrosPerSec; + o_ts->tv_nsec = (i_micros % kMicrosPerSec) * (kNanosPerSec / + kMicrosPerSec); +} + +static inline void osaf_nanos_to_timespec(uint64_t i_nanos, + struct timespec* o_ts) +{ + o_ts->tv_sec = i_nanos / kNanosPerSec; + o_ts->tv_nsec = i_nanos % kNanosPerSec; +} + +static inline void osaf_double_to_timespec(double i_seconds, + struct timespec* o_ts) +{ + o_ts->tv_sec = i_seconds; + o_ts->tv_nsec = (i_seconds - o_ts->tv_sec) * kNanosPerSec; + osaf_normalize_timespec(o_ts, o_ts); +} + +static inline uint64_t osaf_timespec_to_millis(const struct timespec* i_ts) +{ + return i_ts->tv_sec * (uint64_t) kMillisPerSec + i_ts->tv_nsec / + (kNanosPerSec / kMillisPerSec); +} + +static inline uint64_t osaf_timespec_to_micros(const struct timespec* i_ts) +{ + return i_ts->tv_sec * (uint64_t) kMicrosPerSec + i_ts->tv_nsec / + (kNanosPerSec / kMicrosPerSec); +} + +static inline uint64_t osaf_timespec_to_nanos(const struct timespec* i_ts) +{ + return i_ts->tv_sec * (uint64_t) kNanosPerSec + i_ts->tv_nsec; +} + +static inline double osaf_timespec_to_double(const struct timespec* i_ts) +{ + return i_ts->tv_sec + i_ts->tv_nsec / (double) kNanosPerSec; +} + +#ifdef __cplusplus +} +#endif + +#endif /* OPENSAF_BASE_OSAF_TIME_H_ */ diff --git a/osaf/libs/core/common/osaf_poll.c b/osaf/libs/core/common/osaf_poll.c new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/osaf_poll.c @@ -0,0 +1,130 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2013 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#include "osaf_poll.h" +#include <errno.h> +#include <limits.h> +#include "osaf_time.h" +#include "osaf_utility.h" + +static unsigned osaf_poll_no_timeout(struct pollfd* io_fds, nfds_t i_nfds); + +static unsigned osaf_poll_no_timeout(struct pollfd* io_fds, nfds_t i_nfds) +{ + int result; + for (;;) { + result = poll(io_fds, i_nfds, -1); + if (result >= 0) break; + if (result < 0 && errno != EINTR) osaf_abort(result); + } + return result; +} + +unsigned osaf_poll(struct pollfd* io_fds, nfds_t i_nfds, int i_timeout) +{ + struct timespec timeout_ts; + if (i_timeout < 0) return osaf_poll_no_timeout(io_fds, i_nfds); + osaf_millis_to_timespec(i_timeout, &timeout_ts); + return osaf_ppoll(io_fds, i_nfds, &timeout_ts, NULL); +} + +unsigned osaf_ppoll(struct pollfd* io_fds, nfds_t i_nfds, + const struct timespec* i_timeout_ts, const sigset_t* i_sigmask) +{ + static const struct timespec millisecond_round_up = { + 0, (kNanosPerSec / kMillisPerSec) - 1 + }; + static const struct timespec max_possible_timeout = { + INT_MAX / kMillisPerSec, + (INT_MAX % kMillisPerSec) * (kNanosPerSec / kMillisPerSec) + }; + struct timespec start_time; + struct timespec time_left_ts; + int result; + + if (i_sigmask != NULL) osaf_abort(EINVAL); + if (i_timeout_ts == NULL) return osaf_poll_no_timeout(io_fds, i_nfds); + + osaf_clock_gettime(CLOCK_MONOTONIC, &start_time); + time_left_ts = *i_timeout_ts; + + for (;;) { + struct timespec current_time; + struct timespec elapsed_time; + int time_left; + + /* We don't want to time-out too early, so round up to next even + * number of milliseconds. + */ + osaf_timespec_add(&time_left_ts, &millisecond_round_up, + &time_left_ts); + + if (osaf_timespec_compare(&time_left_ts, + &max_possible_timeout) < 0) { + time_left = osaf_timespec_to_millis(&time_left_ts); + } else { + time_left = INT_MAX; + } + + /* ppoll() is currently not included in LSB, so we have to use + * poll() here unfortunately. + */ + result = poll(io_fds, i_nfds, time_left); + if (result > 0 || (result == 0 && time_left < INT_MAX)) break; + if (result < 0 && errno != EINTR) osaf_abort(result); + + osaf_clock_gettime(CLOCK_MONOTONIC, ¤t_time); + osaf_timespec_subtract(¤t_time, &start_time, + &elapsed_time); + if (osaf_timespec_compare(¤t_time, &start_time) < 0) { + /* Handle the unlikely case that the elapsed time is + * negative. Shouldn't happen with a monotonic clock, + * but just to be on the safe side. + */ + elapsed_time.tv_sec = 0; + elapsed_time.tv_nsec = 0; + } + if (osaf_timespec_compare(&elapsed_time, i_timeout_ts) >= 0) { + result = 0; + break; + } + osaf_timespec_subtract(i_timeout_ts, &elapsed_time, + &time_left_ts); + } + return result; +} + +int osaf_poll_one_fd(int i_fd, int i_timeout) +{ + struct pollfd set; + unsigned result; + set.fd = i_fd; + set.events = POLLIN; + result = osaf_poll(&set, 1, i_timeout); + if (result == 1) { + if ((set.revents & POLLNVAL) != 0) osaf_abort(set.revents); + if ((set.revents & POLLERR) != 0) { + errno = EIO; + return -1; + } + if ((set.revents & POLLHUP) != 0) { + errno = EPIPE; + return -1; + } + } + return result; +} diff --git a/osaf/libs/core/common/osaf_time.c b/osaf/libs/core/common/osaf_time.c new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/osaf_time.c @@ -0,0 +1,52 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2013 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#include "osaf_time.h" +#include <errno.h> + +void osaf_nanosleep(const struct timespec* i_req) +{ + struct timespec req = *i_req; + struct timespec start_time; + osaf_clock_gettime(CLOCK_MONOTONIC, &start_time); + for (;;) { + struct timespec current_time; + struct timespec elapsed_time; + /* We could have utilised the second parameter to nanosleep(), + * which will return the remaining sleep time in the case + * nanosleep() was interrupted by a signal. But this gives + * inaccurate sleep time, for various reasons. See the man page + * of nanosleep(2) for details. + */ + int result = nanosleep(&req, NULL); + if (result == 0) break; + if (errno != EINTR) osaf_abort(result); + osaf_clock_gettime(CLOCK_MONOTONIC, ¤t_time); + osaf_timespec_subtract(¤t_time, &start_time, + &elapsed_time); + if (osaf_timespec_compare(¤t_time, &start_time) < 0) { + /* Handle the unlikely case that the elapsed time is + * negative. Shouldn't happen with a monotonic clock, + * but just to be on the safe side. + */ + elapsed_time.tv_sec = 0; + elapsed_time.tv_nsec = 0; + } + if (osaf_timespec_compare(&elapsed_time, i_req) >= 0) break; + osaf_timespec_subtract(i_req, &elapsed_time, &req); + } +} ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel