1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2014-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #include <wx/wx.h>
22 #include "wxe_impl.h"
23
24 /* ****************************************************************************
25 * Erlang Commands
26 * ****************************************************************************/
27
wxeCommand()28 wxeCommand::wxeCommand()
29 {
30 }
31
~wxeCommand()32 wxeCommand::~wxeCommand()
33 {
34 Delete();
35 }
36
Delete()37 void wxeCommand::Delete()
38 {
39 int n = 0;
40
41 if(buffer) {
42 while(bin[n].from) {
43 if(bin[n].bin)
44 driver_free_binary(bin[n].bin);
45 n++;
46 }
47 if(len > 64)
48 driver_free(buffer);
49 buffer = NULL;
50 }
51 op = -2;
52 }
53
54 /* ****************************************************************************
55 * wxeFifo
56 * ****************************************************************************/
wxeFifo(unsigned int sz)57 wxeFifo::wxeFifo(unsigned int sz)
58 {
59 m_q = (wxeCommand *) driver_alloc(sizeof(wxeCommand) * sz);
60 m_orig_sz = sz;
61 m_max = sz;
62 m_n = 0;
63 m_first = 0;
64 cb_start = 0;
65 m_old = NULL;
66 for(unsigned int i = 0; i < sz; i++) {
67 m_q[i].buffer = NULL;
68 m_q[i].op = -1;
69 }
70 }
71
~wxeFifo()72 wxeFifo::~wxeFifo() {
73 // dealloc all memory buffers
74 driver_free(m_q);
75 }
76
Get()77 wxeCommand * wxeFifo::Get()
78 {
79 unsigned int pos;
80 do {
81 if(m_n <= 0)
82 return NULL;
83
84 pos = m_first++;
85 m_n--;
86 m_first %= m_max;
87 } while(m_q[pos].op < 0);
88 return &m_q[pos];
89 }
90
Peek(unsigned int * i)91 wxeCommand * wxeFifo::Peek(unsigned int *i)
92 {
93 unsigned int pos;
94 do {
95 if(*i >= m_n || m_n <= 0)
96 return NULL;
97 pos = (m_first+*i) % m_max;
98 (*i)++;
99 } while(m_q[pos].op < 0);
100 return &m_q[pos];
101 }
102
103
Add(int fc,char * cbuf,int buflen,wxe_data * sd)104 int wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd)
105 {
106 unsigned int pos;
107 wxeCommand *curr;
108
109 int n = 0;
110
111 if(m_n == (m_max-1)) { // resize
112 Realloc();
113 }
114
115 pos = (m_first + m_n) % m_max;
116 m_n++;
117
118 curr = &m_q[pos];
119 curr->caller = driver_caller(sd->port_handle);
120 curr->port = sd->port;
121 curr->op = fc;
122 curr->len = buflen;
123 curr->bin[0].from = 0;
124 curr->bin[1].from = 0;
125 curr->bin[2].from = 0;
126
127 if(cbuf) {
128 if(buflen > 64)
129 curr->buffer = (char *) driver_alloc(buflen);
130 else
131 curr->buffer = curr->c_buf;
132 memcpy((void *) curr->buffer, (void *) cbuf, buflen);
133
134 for(unsigned int i=0; i<sd->max_bins; i++) {
135 if(curr->caller == sd->bin[i].from) {
136 sd->bin[i].from = 0; // Mark copied
137 curr->bin[n].bin = sd->bin[i].bin;
138 curr->bin[n].base = sd->bin[i].base;
139 curr->bin[n].size = sd->bin[i].size;
140 curr->bin[n].from = 1;
141 n++;
142 }
143 }
144 } else { // No-op only PING currently
145 curr->buffer = NULL;
146 }
147 return m_n;
148 }
149
Append(wxeCommand * orig)150 void wxeFifo::Append(wxeCommand *orig)
151 {
152 unsigned int pos;
153 wxeCommand *curr;
154 if(m_n == (m_max-1)) { // resize
155 Realloc();
156 }
157
158 pos = (m_first + m_n) % m_max;
159 m_n++;
160
161 curr = &m_q[pos];
162 curr->op = orig->op;
163 if(curr->op == -1) return;
164 curr->caller = orig->caller;
165 curr->port = orig->port;
166 curr->len = orig->len;
167 curr->bin[0] = orig->bin[0];
168 curr->bin[1] = orig->bin[1];
169 curr->bin[2] = orig->bin[2];
170
171 if(orig->len > 64)
172 curr->buffer = orig->buffer;
173 else {
174 curr->buffer = curr->c_buf;
175 memcpy((void *) curr->buffer, (void *) orig->buffer, orig->len);
176 }
177 orig->op = -1;
178 orig->buffer = NULL;
179 orig->bin[0].from = 0;
180 }
181
Realloc()182 void wxeFifo::Realloc()
183 {
184 unsigned int i;
185 unsigned int growth = m_orig_sz / 2;
186 unsigned int new_sz = growth + m_max;
187 unsigned int max = m_max;
188 unsigned int first = m_first;
189 unsigned int n = m_n;
190 wxeCommand * old = m_q;
191 wxeCommand * queue = (wxeCommand *)driver_alloc(new_sz*sizeof(wxeCommand));
192
193 // fprintf(stderr, "\r\nrealloc qsz %d\r\n", new_sz);fflush(stderr);
194
195 m_max=new_sz;
196 m_first = 0;
197 m_n=0;
198 m_q = queue;
199
200 for(i=0; i < n; i++) {
201 unsigned int pos = (i+first)%max;
202 if(old[pos].op >= 0)
203 Append(&old[pos]);
204 }
205
206 for(i = m_n; i < new_sz; i++) { // Reset the rest
207 m_q[i].buffer = NULL;
208 m_q[i].op = -1;
209 }
210 // Can not free old queue here it can be used in the wx thread
211 m_old = old;
212 }
213
214 // Strip end of queue if ops are already taken care of, avoids reallocs
Strip()215 void wxeFifo::Strip()
216 {
217 while((m_n > 0) && (m_q[(m_first + m_n - 1)%m_max].op < -1)) {
218 m_n--;
219 }
220 }
221
Cleanup(unsigned int def)222 unsigned int wxeFifo::Cleanup(unsigned int def)
223 {
224 if(m_old) {
225 driver_free(m_old);
226 m_old = NULL;
227 // Realloced we need to start from the beginning
228 return 0;
229 } else {
230 return def < cb_start? def : cb_start;
231 }
232 }
233
234 /* ****************************************************************************
235 * TreeItemData
236 * ****************************************************************************/
237
wxETreeItemData(int sz,char * data)238 wxETreeItemData::wxETreeItemData(int sz, char * data) {
239 size = sz;
240 bin = (char *) driver_alloc(sz);
241 memcpy(bin, data, sz);
242 }
243
~wxETreeItemData()244 wxETreeItemData::~wxETreeItemData()
245 {
246 driver_free(bin);
247 }
248