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