From: Mathivanan N. P. <mat...@or...> - 2013-11-29 08:48:20
|
Ack. Good that you were able to work on this ticket, would be a good value add. One comment is that, we should log the fd and strerror(errno) in the cases when poll returned 1. In the absence of this information, it would be a big cycle of time loss going back to the field to collect debug information. So basically, after the below condition + result = osaf_poll(&set, 1, i_timeout); + if (result == 1) { Just print fd, revents, strerror(errno) Cheers, Mathi. > -----Original Message----- > From: Anders Widell [mailto:and...@er...] > Sent: Tuesday, October 08, 2013 3:51 PM > To: Ramesh Babu Betham > Cc: ope...@li... > Subject: [devel] [PATCH 1 of 1] base: Add osaf_poll.h and osaf_time.h APIs > [#580] > > 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.clk > trk > _______________________________________________ > Opensaf-devel mailing list > Ope...@li... > https://lists.sourceforge.net/lists/listinfo/opensaf-devel |