Home | History | Annotate | Download | only in common
      1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #ifndef CRAS_UTIL_H_
      7 #define CRAS_UTIL_H_
      8 
      9 #ifdef __cplusplus
     10 extern "C" {
     11 #endif
     12 
     13 #include <poll.h>
     14 #include <time.h>
     15 
     16 #include "cras_types.h"
     17 
     18 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
     19 
     20 #define assert_on_compile(e) ((void)sizeof(char[1 - 2 * !(e)]))
     21 #define assert_on_compile_is_power_of_2(n) \
     22 	assert_on_compile((n) != 0 && (((n) & ((n) - 1)) == 0))
     23 
     24 /* Enables real time scheduling. */
     25 int cras_set_rt_scheduling(int rt_lim);
     26 /* Sets the priority. */
     27 int cras_set_thread_priority(int priority);
     28 /* Sets the niceness level of the current thread. */
     29 int cras_set_nice_level(int nice);
     30 
     31 /* Converts a buffer level from one sample rate to another. */
     32 static inline size_t cras_frames_at_rate(size_t orig_rate, size_t orig_frames,
     33 					 size_t act_rate)
     34 {
     35 	return (orig_frames * act_rate + orig_rate - 1) / orig_rate;
     36 }
     37 
     38 /* Converts a number of frames to a time in a timespec. */
     39 static inline void cras_frames_to_time(unsigned int frames,
     40 				       unsigned int rate,
     41 				       struct timespec *t)
     42 {
     43 	t->tv_sec = frames / rate;
     44 	frames = frames % rate;
     45 	t->tv_nsec = (uint64_t)frames * 1000000000 / rate;
     46 }
     47 
     48 /* Converts a number of frames to a time in a timespec. */
     49 static inline void cras_frames_to_time_precise(unsigned int frames,
     50 					       double rate,
     51 					       struct timespec *t)
     52 {
     53 	double seconds = frames / rate;
     54 	t->tv_sec = (unsigned int)seconds;
     55 	seconds -= t->tv_sec;
     56 	t->tv_nsec = (unsigned int)(seconds * 1000000000);
     57 }
     58 
     59 /* Converts a timespec duration to a frame count. */
     60 static inline unsigned int cras_time_to_frames(const struct timespec *t,
     61 					       unsigned int rate)
     62 {
     63 	return t->tv_nsec * (uint64_t)rate / 1000000000 + rate * t->tv_sec;
     64 }
     65 
     66 /* Converts a number of frames to a duration in ms. */
     67 static inline unsigned int cras_frames_to_ms(unsigned int frames,
     68 					     unsigned int rate)
     69 {
     70 	return 1000 * frames / rate;
     71 }
     72 
     73 /* Makes a file descriptor non blocking. */
     74 int cras_make_fd_nonblocking(int fd);
     75 
     76 /* Makes a file descriptor blocking. */
     77 int cras_make_fd_blocking(int fd);
     78 
     79 /* Send data in buf to the socket attach the fds. */
     80 int cras_send_with_fds(int sockfd, const void *buf, size_t len, int *fd,
     81 		       unsigned int num_fds);
     82 
     83 /* Receive data in buf from the socket. If file descriptors are received, put
     84  * them in *fd, otherwise set *fd to -1. */
     85 int cras_recv_with_fds(int sockfd, void *buf, size_t len, int *fd,
     86 		       unsigned int *num_fds);
     87 
     88 /* This must be written a million times... */
     89 static inline void subtract_timespecs(const struct timespec *end,
     90 				      const struct timespec *beg,
     91 				      struct timespec *diff)
     92 {
     93 	diff->tv_sec = end->tv_sec - beg->tv_sec;
     94 	diff->tv_nsec = end->tv_nsec - beg->tv_nsec;
     95 
     96 	/* Adjust tv_sec and tv_nsec to the same sign. */
     97 	if (diff->tv_sec > 0 && diff->tv_nsec < 0) {
     98 		diff->tv_sec--;
     99 		diff->tv_nsec += 1000000000L;
    100 	} else if (diff->tv_sec < 0 && diff->tv_nsec > 0) {
    101 		diff->tv_sec++;
    102 		diff->tv_nsec -= 1000000000L;
    103 	}
    104 }
    105 
    106 static inline void add_timespecs(struct timespec *a,
    107 				 const struct timespec *b)
    108 {
    109 	a->tv_sec += b->tv_sec;
    110 	a->tv_nsec += b->tv_nsec;
    111 
    112 	while (a->tv_nsec >= 1000000000L) {
    113 		a->tv_sec++;
    114 		a->tv_nsec -= 1000000000L;
    115 	}
    116 }
    117 
    118 /* Converts a fixed-size cras_timespec to a native timespec */
    119 static inline void cras_timespec_to_timespec(struct timespec *dest,
    120 					     const struct cras_timespec *src)
    121 {
    122 	dest->tv_sec = src->tv_sec;
    123 	dest->tv_nsec = src->tv_nsec;
    124 }
    125 
    126 /* Fills a fixed-size cras_timespec with the current system time */
    127 static inline int cras_clock_gettime(clockid_t clk_id,
    128 				     struct cras_timespec *ctp)
    129 {
    130 	struct timespec tp;
    131 	int ret = clock_gettime(clk_id, &tp);
    132 	ctp->tv_sec = tp.tv_sec;
    133 	ctp->tv_nsec = tp.tv_nsec;
    134 	return ret;
    135 }
    136 
    137 /* Returns true if timeval a is after timeval b */
    138 static inline int timeval_after(const struct timeval *a,
    139 				const struct timeval *b)
    140 {
    141 	return (a->tv_sec > b->tv_sec) ||
    142 		(a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec);
    143 }
    144 
    145 /* Returns true if timespec a is after timespec b */
    146 static inline int timespec_after(const struct timespec *a,
    147 				 const struct timespec *b)
    148 {
    149 	return (a->tv_sec > b->tv_sec) ||
    150 		(a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec);
    151 }
    152 
    153 /* Retruns the equivalent number of milliseconds for a given timespec.
    154  * The result is rounded up to the next millisecond. */
    155 static inline unsigned int timespec_to_ms(const struct timespec *ts)
    156 {
    157 	return ts->tv_sec * 1000 + (ts->tv_nsec + 999999) / 1000000;
    158 }
    159 
    160 /* Convert milliseconds to timespec. */
    161 static inline void ms_to_timespec(time_t milliseconds, struct timespec *ts)
    162 {
    163 	ts->tv_sec = milliseconds / 1000;
    164 	ts->tv_nsec = (milliseconds % 1000) * 1000000;
    165 }
    166 
    167 /* Returns non-zero if the given timespec is non-zero. */
    168 static inline int timespec_is_nonzero(const struct timespec *ts) {
    169 	return ts && (ts->tv_sec != 0 ||
    170 		      (ts->tv_sec == 0 && ts->tv_nsec != 0));
    171 }
    172 
    173 /* Calculates frames since time beg. */
    174 static inline unsigned int cras_frames_since_time(const struct timespec *beg,
    175 						  unsigned int rate)
    176 {
    177 	struct timespec now, time_since;
    178 
    179 	clock_gettime(CLOCK_MONOTONIC_RAW, &now);
    180 	if (!timespec_after(&now, beg))
    181 		return 0;
    182 
    183 	subtract_timespecs(&now, beg, &time_since);
    184 	return cras_time_to_frames(&time_since, rate);
    185 }
    186 
    187 /* Poll on the given file descriptors.
    188  *
    189  * See ppoll(). This implementation changes the value of timeout to the
    190  * remaining time, and returns negative error codes on error.
    191  *
    192  * Args:
    193  *    fds - Array of pollfd structures.
    194  *    nfds - Number of pollfd structures.
    195  *    timeout - Timeout time updated upon return with remaining time. The
    196  *              timeout value may be updated to become invalid (negative
    197  *              tv_nsec or negative tv_sec). In that case, -tv_nsec is the
    198  *              number of nanoseconds by which the polling exceeded the
    199  *              supplied timeout. The function immediately returns with
    200  *              -ETIMEOUT if tv_nsec is negative, simplifying loops that
    201  *              rely on the returned remaining timeout.
    202  *    sigmask - Signal mask while in the poll.
    203  *
    204  * Returns:
    205  *    Positive when file decriptors are ready.
    206  *    Zero if no file descriptors are ready and timeout is NULL.
    207  *    -ETIMEDOUT when no file descriptors are ready and a timeout specified.
    208  *    Other negative error codes specified in the ppoll() man page.
    209  */
    210 int cras_poll(struct pollfd *fds, nfds_t nfds, struct timespec *timeout,
    211               const sigset_t *sigmask);
    212 
    213 /* Wait for /dev/input/event* files to become accessible.
    214  *
    215  * Returns:
    216  *   Zero on success. Otherwise a negative error code.
    217  */
    218 int wait_for_dev_input_access();
    219 
    220 #ifdef __cplusplus
    221 } /* extern "C" */
    222 #endif
    223 
    224 #endif /* CRAS_UTIL_H_ */
    225