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
6 #include <stdlib.h>
7 #include <sys/param.h>
8
9 #include "cras_types.h"
10 #include "buffer_share.h"
11
find_unused(const struct buffer_share * mix)12 static inline struct id_offset *find_unused(const struct buffer_share *mix)
13 {
14 unsigned int i;
15
16 for (i = 0; i < mix->id_sz; i++) {
17 if (!mix->wr_idx[i].used)
18 return &mix->wr_idx[i];
19 }
20
21 return NULL;
22 }
23
24
find_id(const struct buffer_share * mix,unsigned int id)25 static inline struct id_offset *find_id(const struct buffer_share *mix,
26 unsigned int id)
27 {
28 unsigned int i;
29
30 for (i = 0; i < mix->id_sz; i++) {
31 if (mix->wr_idx[i].used && id == mix->wr_idx[i].id)
32 return &mix->wr_idx[i];
33 }
34
35 return NULL;
36 }
37
alloc_more_ids(struct buffer_share * mix)38 static void alloc_more_ids(struct buffer_share *mix)
39 {
40 unsigned int new_size = mix->id_sz * 2;
41 unsigned int i;
42
43 mix->wr_idx = realloc(mix->wr_idx, sizeof(mix->wr_idx[0]) * new_size);
44
45 for (i = mix->id_sz; i < new_size; i++)
46 mix->wr_idx[i].used = 0;
47
48 mix->id_sz = new_size;
49 }
50
buffer_share_create(unsigned int buf_sz)51 struct buffer_share *buffer_share_create(unsigned int buf_sz)
52 {
53 struct buffer_share *mix;
54
55 mix = calloc(1, sizeof(*mix));
56 mix->id_sz = INITIAL_ID_SIZE;
57 mix->wr_idx = calloc(mix->id_sz, sizeof(mix->wr_idx[0]));
58 mix->buf_sz = buf_sz;
59
60 return mix;
61 }
62
buffer_share_destroy(struct buffer_share * mix)63 void buffer_share_destroy(struct buffer_share *mix)
64 {
65 if (!mix)
66 return;
67 free(mix->wr_idx);
68 free(mix);
69 }
70
buffer_share_add_id(struct buffer_share * mix,unsigned int id,void * data)71 int buffer_share_add_id(struct buffer_share *mix, unsigned int id, void *data)
72 {
73 struct id_offset *o;
74
75 o = find_id(mix, id);
76 if (o)
77 return -EEXIST;
78
79 o = find_unused(mix);
80 if (!o)
81 alloc_more_ids(mix);
82
83 o = find_unused(mix);
84 o->used = 1;
85 o->id = id;
86 o->offset = 0;
87 o->data = data;
88
89 return 0;
90 }
91
buffer_share_rm_id(struct buffer_share * mix,unsigned int id)92 int buffer_share_rm_id(struct buffer_share *mix, unsigned int id)
93 {
94 struct id_offset *o;
95
96 o = find_id(mix, id);
97 if (!o)
98 return -ENOENT;
99 o->used = 0;
100 o->data = NULL;
101
102 return 0;
103 }
104
buffer_share_offset_update(struct buffer_share * mix,unsigned int id,unsigned int delta)105 int buffer_share_offset_update(struct buffer_share *mix, unsigned int id,
106 unsigned int delta)
107 {
108 unsigned int i;
109
110 for (i = 0; i < mix->id_sz; i++) {
111 if (id != mix->wr_idx[i].id)
112 continue;
113
114 mix->wr_idx[i].offset += delta;
115 break;
116 }
117
118 return 0;
119 }
120
buffer_share_get_new_write_point(struct buffer_share * mix)121 unsigned int buffer_share_get_new_write_point(struct buffer_share *mix)
122 {
123 unsigned int min_written = mix->buf_sz + 1;
124 unsigned int i;
125
126 for (i = 0; i < mix->id_sz; i++) {
127 struct id_offset *o = &mix->wr_idx[i];
128
129 if (!o->used)
130 continue;
131
132 min_written = MIN(min_written, o->offset);
133 }
134 for (i = 0; i < mix->id_sz; i++) {
135 struct id_offset *o = &mix->wr_idx[i];
136 o->offset -= min_written;
137 }
138
139 if (min_written > mix->buf_sz)
140 return 0;
141
142 return min_written;
143 }
144
get_id_offset(const struct buffer_share * mix,unsigned int id)145 static struct id_offset *get_id_offset(const struct buffer_share *mix,
146 unsigned int id)
147 {
148 unsigned int i;
149 struct id_offset *o;
150
151 for (i = 0; i < mix->id_sz; i++) {
152 o = &mix->wr_idx[i];
153 if (o->used && o->id == id)
154 return o;
155 }
156 return NULL;
157 }
158
buffer_share_id_offset(const struct buffer_share * mix,unsigned int id)159 unsigned int buffer_share_id_offset(const struct buffer_share *mix,
160 unsigned int id)
161 {
162 struct id_offset *o = get_id_offset(mix, id);
163 return o ? o->offset : 0;
164 }
165
buffer_share_get_data(const struct buffer_share * mix,unsigned int id)166 void *buffer_share_get_data(const struct buffer_share *mix,
167 unsigned int id)
168 {
169 struct id_offset *o = get_id_offset(mix, id);
170 return o ? o->data : NULL;
171 }
172