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,
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. */
cras_frames_to_time_precise(unsigned int frames,double rate,struct timespec * t)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. */
cras_time_to_frames(const struct timespec * t,unsigned int rate)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. */
cras_frames_to_ms(unsigned int frames,unsigned int rate)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... */
subtract_timespecs(const struct timespec * end,const struct timespec * beg,struct timespec * diff)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
add_timespecs(struct timespec * a,const struct timespec * b)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 */
cras_timespec_to_timespec(struct timespec * dest,const struct cras_timespec * src)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 */
cras_clock_gettime(clockid_t clk_id,struct cras_timespec * ctp)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 */
timeval_after(const struct timeval * a,const struct 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 */
timespec_after(const struct timespec * a,const struct 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. */
timespec_to_ms(const struct timespec * ts)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. */
ms_to_timespec(time_t milliseconds,struct timespec * ts)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. */
timespec_is_nonzero(const struct timespec * ts)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. */
cras_frames_since_time(const struct timespec * beg,unsigned int rate)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