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