2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <sys/types.h>
27 #include <audio_utils/fifo.h>
28 #include <cutils/ashmem.h>
30 #define FRAME_COUNT 2048
31 #define FRAME_SIZE sizeof(int16_t)
32 #define BUFFER_SIZE (FRAME_COUNT * FRAME_SIZE)
34 int main(int argc __unused, char **argv __unused)
36 // TODO Add error checking for ashmem_create_region and mmap
38 const int frontFd = ashmem_create_region("front", sizeof(audio_utils_fifo_index));
39 printf("frontFd=%d\n", frontFd);
41 const int rearFd = ashmem_create_region("rear", sizeof(audio_utils_fifo_index));
42 printf("rearFd=%d\n", rearFd);
44 const int dataFd = ashmem_create_region("buffer", BUFFER_SIZE);
45 printf("dataFd=%d\n", dataFd);
47 // next two index constructors must execute exactly once, so we do it in the parent
49 audio_utils_fifo_index *frontIndex = (audio_utils_fifo_index *) mmap(NULL,
50 sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, frontFd, (off_t) 0);
51 printf("parent frontIndex=%p\n", frontIndex);
52 (void) new(frontIndex) audio_utils_fifo_index();
54 audio_utils_fifo_index *rearIndex = (audio_utils_fifo_index *) mmap(NULL,
55 sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, rearFd, (off_t) 0);
56 printf("parent rearIndex=%p\n", rearIndex);
57 (void) new(rearIndex) audio_utils_fifo_index();
59 int16_t *data = (int16_t *) mmap(NULL, sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE,
60 MAP_SHARED, dataFd, (off_t) 0);
61 printf("parent data=%p\n", data);
62 memset(data, 0, BUFFER_SIZE);
64 const int pageSize = getpagesize();
65 printf("page size=%d\n", pageSize);
69 printf("fork writer:\n");
70 const pid_t pidWriter = fork();
71 // TODO check if pidWriter < 0
74 // Child inherits the parent's read/write mapping of front index.
75 // To confirm that there are no attempts to write to the front index,
76 // unmap it and then re-map it as read-only.
77 int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
78 printf("writer unmap front ok=%d\n", ok);
79 ok = ashmem_set_prot_region(frontFd, PROT_READ);
80 printf("writer prot read front ok=%d\n", ok);
81 // The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
82 frontIndex = (audio_utils_fifo_index *) mmap((char *) frontIndex + pageSize * 4,
83 sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, frontFd,
85 printf("writer frontIndex=%p\n", frontIndex);
87 // Retain our read/write mapping of rear index and data
88 audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
89 audio_utils_fifo_writer writer(fifo);
93 for (int16_t value = 1; value <= 20; value++) {
94 printf("writing %d\n", value);
95 const ssize_t actual = writer.write(&value, 1);
97 printf("wrote unexpected actual = %zd\n", actual);
100 // TODO needs a lot of work
114 (void) close(frontFd);
115 (void) close(rearFd);
116 (void) close(dataFd);
121 // The sleep(2) above and sleep(1) here ensure that the order is:
122 // a. writer initializes
123 // b. reader initializes
124 // c. reader starts the read loop
125 // d. writer starts the write loop
126 // Actually, as long as (a) precedes (d) and (b) precedes (c), the order does not matter.
127 // TODO test all valid sequences.
132 printf("fork reader:\n");
133 const pid_t pidReader = fork();
134 // TODO check if pidReader < 0
137 // Child inherits the parent's read/write mapping of rear index.
138 // To confirm that there are no attempts to write to the rear index,
139 // unmap it and then re-map it as read-only.
140 int ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
141 printf("reader unmap rear ok=%d\n", ok);
142 ok = ashmem_set_prot_region(rearFd, PROT_READ);
143 printf("reader prot read rear ok=%d\n", ok);
144 // The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
145 rearIndex = (audio_utils_fifo_index *) mmap((char *) rearIndex + pageSize * 4,
146 sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, rearFd,
148 printf("reader rearIndex=%p\n", rearIndex);
150 // Similarly for the data
151 ok = munmap(data, BUFFER_SIZE);
152 printf("reader unmap data ok=%d\n", ok);
153 ok = ashmem_set_prot_region(dataFd, PROT_READ);
154 printf("reader prot read data ok=%d\n", ok);
155 // The pagesize * 8 offset confirms that we don't assume identical mapping in both processes
156 data = (int16_t *) mmap((char *) data + pageSize * 8, BUFFER_SIZE, PROT_READ,
157 MAP_SHARED | MAP_FIXED, dataFd, (off_t) 0);
158 printf("reader data=%p\n", data);
160 // Retain our read/write mapping of front index
161 audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
162 audio_utils_fifo_reader reader(fifo);
166 struct timespec timeout = {
170 const ssize_t actual = reader.read(&value, 1, &timeout);
175 printf("read %d\n", value);
181 printf("read timed out\n");
184 printf("read unexpected actual = %zd\n", actual);
190 (void) close(frontFd);
191 (void) close(rearFd);
192 (void) close(dataFd);
198 pid_t pid = waitpid(pidWriter, &status, 0);
199 if (pid == pidWriter) {
200 printf("writer exited with status %d\n", status);
202 printf("waitpid on writer = %d\n", pid);
204 pid = waitpid(pidReader, &status, 0);
205 if (pid == pidReader) {
206 printf("reader exited with status %d\n", status);
208 printf("waitpid on reader = %d\n", pid);
211 // next two index destructors must execute exactly once, so we do it in the parent
212 frontIndex->~audio_utils_fifo_index();
213 rearIndex->~audio_utils_fifo_index();
215 int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
216 printf("parent unmap front ok=%d\n", ok);
217 ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
218 printf("parent unmap rear ok=%d\n", ok);
219 ok = munmap(data, BUFFER_SIZE);
220 printf("parent unmap data ok=%d\n", ok);
222 (void) close(frontFd);
223 (void) close(rearFd);
224 (void) close(dataFd);