• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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. */
cras_frames_at_rate(size_t orig_rate,size_t orig_frames,size_t act_rate)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. */
cras_frames_to_time(unsigned int frames,unsigned int rate,struct timespec * t)39 static inline void cras_frames_to_time(unsigned int frames, unsigned int rate,
40 				       struct timespec *t)
41 {
42 	t->tv_sec = frames / rate;
43 	frames = frames % rate;
44 	t->tv_nsec = (uint64_t)frames * 1000000000 / rate;
45 }
46 
47 /* Converts a number of frames to a time in a timespec. */
cras_frames_to_time_precise(unsigned int frames,double rate,struct timespec * t)48 static inline void cras_frames_to_time_precise(unsigned int frames, double rate,
49 					       struct timespec *t)
50 {
51 	double seconds = frames / rate;
52 	t->tv_sec = (unsigned int)seconds;
53 	seconds -= t->tv_sec;
54 	t->tv_nsec = (unsigned int)(seconds * 1000000000);
55 }
56 
57 /* Converts a timespec duration to a frame count. */
cras_time_to_frames(const struct timespec * t,unsigned int rate)58 static inline uint64_t cras_time_to_frames(const struct timespec *t,
59 					   unsigned int rate)
60 {
61 	return t->tv_nsec * (uint64_t)rate / 1000000000 + rate * t->tv_sec;
62 }
63 
64 /* Converts a number of frames to a duration in ms. */
cras_frames_to_ms(unsigned int frames,unsigned int rate)65 static inline unsigned int cras_frames_to_ms(unsigned int frames,
66 					     unsigned int rate)
67 {
68 	return 1000 * frames / rate;
69 }
70 
71 /* Makes a file descriptor non blocking. */
72 int cras_make_fd_nonblocking(int fd);
73 
74 /* Makes a file descriptor blocking. */
75 int cras_make_fd_blocking(int fd);
76 
77 /* Send data in buf to the socket attach the fds. */
78 int cras_send_with_fds(int sockfd, const void *buf, size_t len, int *fd,
79 		       unsigned int num_fds);
80 
81 /* Receive data in buf from the socket. If file descriptors are received, put
82  * them in *fd, otherwise set *fd to -1. */
83 int cras_recv_with_fds(int sockfd, void *buf, size_t len, int *fd,
84 		       unsigned int *num_fds);
85 
86 /* This must be written a million times... */
subtract_timespecs(const struct timespec * end,const struct timespec * beg,struct timespec * diff)87 static inline void subtract_timespecs(const struct timespec *end,
88 				      const struct timespec *beg,
89 				      struct timespec *diff)
90 {
91 	diff->tv_sec = end->tv_sec - beg->tv_sec;
92 	diff->tv_nsec = end->tv_nsec - beg->tv_nsec;
93 
94 	/* Adjust tv_sec and tv_nsec to the same sign. */
95 	if (diff->tv_sec > 0 && diff->tv_nsec < 0) {
96 		diff->tv_sec--;
97 		diff->tv_nsec += 1000000000L;
98 	} else if (diff->tv_sec < 0 && diff->tv_nsec > 0) {
99 		diff->tv_sec++;
100 		diff->tv_nsec -= 1000000000L;
101 	}
102 }
103 
add_timespecs(struct timespec * a,const struct timespec * b)104 static inline void add_timespecs(struct timespec *a, const struct timespec *b)
105 {
106 	a->tv_sec += b->tv_sec;
107 	a->tv_nsec += b->tv_nsec;
108 
109 	while (a->tv_nsec >= 1000000000L) {
110 		a->tv_sec++;
111 		a->tv_nsec -= 1000000000L;
112 	}
113 }
114 
115 /* Converts a fixed-size cras_timespec to a native timespec */
cras_timespec_to_timespec(struct timespec * dest,const struct cras_timespec * src)116 static inline void cras_timespec_to_timespec(struct timespec *dest,
117 					     const struct cras_timespec *src)
118 {
119 	dest->tv_sec = src->tv_sec;
120 	dest->tv_nsec = src->tv_nsec;
121 }
122 
123 /* Fills a fixed-size cras_timespec with the current system time */
cras_clock_gettime(clockid_t clk_id,struct cras_timespec * ctp)124 static inline int cras_clock_gettime(clockid_t clk_id,
125 				     struct cras_timespec *ctp)
126 {
127 	struct timespec tp;
128 	int ret = clock_gettime(clk_id, &tp);
129 	ctp->tv_sec = tp.tv_sec;
130 	ctp->tv_nsec = tp.tv_nsec;
131 	return ret;
132 }
133 
134 /* Returns true if timeval a is after timeval b */
timeval_after(const struct timeval * a,const struct timeval * b)135 static inline int timeval_after(const struct timeval *a,
136 				const struct timeval *b)
137 {
138 	return (a->tv_sec > b->tv_sec) ||
139 	       (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec);
140 }
141 
142 /* Returns true if timespec a is after timespec b */
timespec_after(const struct timespec * a,const struct timespec * b)143 static inline int timespec_after(const struct timespec *a,
144 				 const struct timespec *b)
145 {
146 	return (a->tv_sec > b->tv_sec) ||
147 	       (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec);
148 }
149 
150 /* Retruns the equivalent number of milliseconds for a given timespec.
151  * The result is rounded up to the next millisecond. */
timespec_to_ms(const struct timespec * ts)152 static inline unsigned int timespec_to_ms(const struct timespec *ts)
153 {
154 	return ts->tv_sec * 1000 + (ts->tv_nsec + 999999) / 1000000;
155 }
156 
157 /* Convert milliseconds to timespec. */
ms_to_timespec(time_t milliseconds,struct timespec * ts)158 static inline void ms_to_timespec(time_t milliseconds, struct timespec *ts)
159 {
160 	ts->tv_sec = milliseconds / 1000;
161 	ts->tv_nsec = (milliseconds % 1000) * 1000000;
162 }
163 
164 /* Returns true if the given timespec is zero. */
timespec_is_zero(const struct timespec * ts)165 static inline int timespec_is_zero(const struct timespec *ts)
166 {
167 	return ts && ts->tv_sec == 0 && ts->tv_nsec == 0;
168 }
169 
170 /* Returns non-zero if the given timespec is non-zero. */
timespec_is_nonzero(const struct timespec * ts)171 static inline int timespec_is_nonzero(const struct timespec *ts)
172 {
173 	return ts && (ts->tv_sec != 0 || (ts->tv_sec == 0 && ts->tv_nsec != 0));
174 }
175 
176 /* Calculates frames since time beg. */
cras_frames_since_time(const struct timespec * beg,unsigned int rate)177 static inline uint64_t cras_frames_since_time(const struct timespec *beg,
178 					      unsigned int rate)
179 {
180 	struct timespec now, time_since;
181 
182 	clock_gettime(CLOCK_MONOTONIC_RAW, &now);
183 	if (!timespec_after(&now, beg))
184 		return 0;
185 
186 	subtract_timespecs(&now, beg, &time_since);
187 	return cras_time_to_frames(&time_since, rate);
188 }
189 
190 /* Calculates frames until time end. */
cras_frames_until_time(const struct timespec * end,unsigned int rate)191 static inline uint64_t cras_frames_until_time(const struct timespec *end,
192 					      unsigned int rate)
193 {
194 	struct timespec now, time_until;
195 
196 	clock_gettime(CLOCK_MONOTONIC_RAW, &now);
197 	if (!timespec_after(end, &now))
198 		return 0;
199 
200 	subtract_timespecs(end, &now, &time_until);
201 	return cras_time_to_frames(&time_until, rate);
202 }
203 
204 /* Returns true if the difference between a and b is  shorter than t. */
timespec_diff_shorter_than(const struct timespec * a,const struct timespec * b,const struct timespec * t)205 static inline bool timespec_diff_shorter_than(const struct timespec *a,
206 					      const struct timespec *b,
207 					      const struct timespec *t)
208 {
209 	struct timespec diff;
210 	if (timespec_after(a, b))
211 		subtract_timespecs(a, b, &diff);
212 	else
213 		subtract_timespecs(b, a, &diff);
214 	return timespec_after(t, &diff);
215 }
216 
217 /* Poll on the given file descriptors.
218  *
219  * See ppoll(). This implementation changes the value of timeout to the
220  * remaining time, and returns negative error codes on error.
221  *
222  * Args:
223  *    fds - Array of pollfd structures.
224  *    nfds - Number of pollfd structures.
225  *    timeout - Timeout time updated upon return with remaining time. The
226  *              timeout value may be updated to become invalid (negative
227  *              tv_nsec or negative tv_sec). In that case, -tv_nsec is the
228  *              number of nanoseconds by which the polling exceeded the
229  *              supplied timeout. The function immediately returns with
230  *              -ETIMEOUT if tv_nsec is negative, simplifying loops that
231  *              rely on the returned remaining timeout.
232  *    sigmask - Signal mask while in the poll.
233  *
234  * Returns:
235  *    Positive when file decriptors are ready.
236  *    Zero if no file descriptors are ready and timeout is NULL.
237  *    -ETIMEDOUT when no file descriptors are ready and a timeout specified.
238  *    Other negative error codes specified in the ppoll() man page.
239  */
240 int cras_poll(struct pollfd *fds, nfds_t nfds, struct timespec *timeout,
241 	      const sigset_t *sigmask);
242 
243 /* Wait for /dev/input/event* files to become accessible.
244  *
245  * Returns:
246  *   Zero on success. Otherwise a negative error code.
247  */
248 int wait_for_dev_input_access();
249 
250 #ifdef __cplusplus
251 } /* extern "C" */
252 #endif
253 
254 #endif /* CRAS_UTIL_H_ */
255