1 /* Copyright (c) 2014 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 * The blow logging funcitons must only be called from the audio thread.
6 */
7
8 #ifndef AUDIO_THREAD_LOG_H_
9 #define AUDIO_THREAD_LOG_H_
10
11 #include <sys/mman.h>
12 #include <pthread.h>
13 #include <stdint.h>
14 #include <syslog.h>
15
16 #include "cras_types.h"
17 #include "cras_shm.h"
18
19 #define AUDIO_THREAD_LOGGING 1
20
21 #if (AUDIO_THREAD_LOGGING)
22 #define ATLOG(log, event, data1, data2, data3) \
23 audio_thread_event_log_data(log, event, data1, data2, data3);
24 #else
25 #define ATLOG(log, event, data1, data2, data3)
26 #endif
27
28 extern struct audio_thread_event_log *atlog;
29 extern int atlog_rw_shm_fd;
30 extern int atlog_ro_shm_fd;
31
32 static inline struct audio_thread_event_log *
audio_thread_event_log_init(char * name)33 audio_thread_event_log_init(char *name)
34 {
35 struct audio_thread_event_log *log;
36
37 atlog_ro_shm_fd = -1;
38 atlog_rw_shm_fd = -1;
39
40 log = (struct audio_thread_event_log *)cras_shm_setup(
41 name, sizeof(*log), &atlog_rw_shm_fd, &atlog_ro_shm_fd);
42 /* Fallback to calloc if device shared memory resource is empty and
43 * cras_shm_setup fails.
44 */
45 if (log == NULL) {
46 syslog(LOG_ERR, "Failed to create atlog by cras_shm_setup");
47 log = (struct audio_thread_event_log *)calloc(
48 1, sizeof(struct audio_thread_event_log));
49 }
50 log->len = AUDIO_THREAD_EVENT_LOG_SIZE;
51
52 return log;
53 }
54
55 static inline void
audio_thread_event_log_deinit(struct audio_thread_event_log * log,char * name)56 audio_thread_event_log_deinit(struct audio_thread_event_log *log, char *name)
57 {
58 if (log) {
59 if (atlog_rw_shm_fd >= 0) {
60 munmap(log, sizeof(*log));
61 cras_shm_close_unlink(name, atlog_rw_shm_fd);
62 } else {
63 free(log);
64 }
65
66 if (atlog_ro_shm_fd >= 0)
67 close(atlog_ro_shm_fd);
68 }
69 }
70
71 /* Log a tag and the current time, Uses two words, the first is split
72 * 8 bits for tag and 24 for seconds, second word is micro seconds.
73 */
74 static inline void
audio_thread_event_log_data(struct audio_thread_event_log * log,enum AUDIO_THREAD_LOG_EVENTS event,uint32_t data1,uint32_t data2,uint32_t data3)75 audio_thread_event_log_data(struct audio_thread_event_log *log,
76 enum AUDIO_THREAD_LOG_EVENTS event, uint32_t data1,
77 uint32_t data2, uint32_t data3)
78 {
79 struct timespec now;
80 uint64_t pos_mod_len = log->write_pos % AUDIO_THREAD_EVENT_LOG_SIZE;
81 clock_gettime(CLOCK_MONOTONIC_RAW, &now);
82
83 log->log[pos_mod_len].tag_sec =
84 (event << 24) | (now.tv_sec & 0x00ffffff);
85 log->log[pos_mod_len].nsec = now.tv_nsec;
86 log->log[pos_mod_len].data1 = data1;
87 log->log[pos_mod_len].data2 = data2;
88 log->log[pos_mod_len].data3 = data3;
89
90 log->write_pos++;
91 }
92
93 #endif /* AUDIO_THREAD_LOG_H_ */
94