Hi Anders,

I am not sure on the motivation behind adding more utilities to 
core/leap area.

Also to what extent all these utility functions are used by OpenSAF 
services?. Because on behalf of ticket# 537, I am cleaning up the unused 
code from leap area and adding more utilities with out actually using 
them doesn't make sense.

Some of the minor comments on osaf_time are inline with [Ramesh].

Coming to the osaf_poll, I have not reviewed yet. But my general comment 
is.. Already we have poll utility in os_defs.c 
(ncs_sel_obj_poll_single_obj()). Any additional poll specific utility 
functions (if they are subjected to use by OpenSAF svc's) can be added 
in os_defs.c itself.

Thanks and Regards,
Ramesh.

On 10/8/2013 3:51 PM, Anders Widell wrote:
>   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.
> +      */
[Ramesh]: Comment correction: should be microseconds, below should be 
milliseconds
> +     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;
> +}
[Ramesh]: Above function should take care of comparing i_end and i_start 
tmr values and should take appropriate action.

> +
> +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;
> +}
[Ramesh]: In above function, better the expression having having 
(kNanosPerSec / kMicorsPerSec) rather than (kMicrosPerSec / 
kMillisPerSec). Similarly for the below function too.
> +
> +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);
> +}
> +
[Ramesh]: Not able to understand the above logic?
> +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, &current_time);
> +             osaf_timespec_subtract(&current_time, &start_time,
> +                     &elapsed_time);
> +             if (osaf_timespec_compare(&current_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, &current_time);
> +             osaf_timespec_subtract(&current_time, &start_time,
> +                     &elapsed_time);
> +             if (osaf_timespec_compare(&current_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);
> +     }
> +}

------------------------------------------------------------------------------
Android is increasing in popularity, but the open development platform that
developers love is also attractive to malware creators. Download this white
paper to learn more about secure code signing practices that can help keep
Android apps secure.
http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to