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