FreeCalypso > hg > freecalypso-sw
comparison gsm-fw/riviera/rvf/rvf_buffer.c @ 143:afceeeb2cba1
Our nuc-fw is destined to become gsm-fw, so I went ahead and did the big hg mv
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 12 Nov 2013 05:35:48 +0000 |
parents | nuc-fw/riviera/rvf/rvf_buffer.c@dd56546ad9e0 |
children |
comparison
equal
deleted
inserted
replaced
142:15d5977390c2 | 143:afceeeb2cba1 |
---|---|
1 /****************************************************************************/ | |
2 /* */ | |
3 /* Name rvf_buffer.c */ | |
4 /* */ | |
5 /* Function this file contains rvf buffer handling functions */ | |
6 /* */ | |
7 /* Version 0.1 */ | |
8 /* */ | |
9 /* Date Modification */ | |
10 /* ------------------------------------ */ | |
11 /* 3/12/99 Create */ | |
12 /* 10/27/1999 remove all non-nucleus sections (#ifdef) */ | |
13 /* 30/11/1999 compliant to RV coding guidelines */ | |
14 /* 12/23/1999 change buffer management, add memory bank handling and */ | |
15 /* remove useless functions */ | |
16 /* 07/12/2000 implement dynamic memory allocation. */ | |
17 /* */ | |
18 /* Author David Lamy-Charrier (dlamy@tif.ti.com) */ | |
19 /* */ | |
20 /* (C) Copyright 1999 by Texas Instruments Incorporated, All Rights Reserved*/ | |
21 /****************************************************************************/ | |
22 | |
23 #include "../../include/config.h" | |
24 | |
25 #include "../rvm/rvm_use_id_list.h" | |
26 #include "rvf_api.h" | |
27 #include "rvf_i.h" | |
28 #include "../support/exception.h" | |
29 #include "rvf_pool_size.h" | |
30 | |
31 #include "../../nucleus/nucleus.h" | |
32 | |
33 #include <string.h> | |
34 #include <stdio.h> | |
35 | |
36 | |
37 #if RVF_ENABLE_STATS /* conditional inclusion of stdio.h for sprintf() function */ | |
38 #ifdef _WINDOWS | |
39 #include <stdio.h> | |
40 #endif | |
41 #endif | |
42 | |
43 #include "../rv/rv_defined_swe.h" | |
44 | |
45 #ifdef RVM_DAR_SWE | |
46 #include "dar/dar_api.h" | |
47 #endif | |
48 #define RVF_INVALID_MD_ID_ERRROR ("RVF: Invalid MB ID") | |
49 | |
50 #define INC_END_INITIALIZE 2 | |
51 #define RVF_INVALID_INDEX 0xFFFF | |
52 | |
53 /************* TASK MAILBOXES *******************/ | |
54 /* chained lists for task mailboxes */ | |
55 T_RVF_INTERNAL_BUF *OSTaskQFirst[1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX]; | |
56 T_RVF_INTERNAL_BUF *OSTaskQLast [1][1]; //[MAX_RVF_TASKS][RVF_NUM_TASK_MBOX]; | |
57 | |
58 extern INC_Initialize_State; | |
59 | |
60 T_RVF_RT_ADDR_ID_DATA* pRtAddrIdTable[MAX_RVF_G_ADDR_ID]; | |
61 | |
62 | |
63 /******** MEMORY POOLS ******************/ | |
64 /* Define the buffer pools */ | |
65 extern T_RVF_POOL _rvf_pools[]; | |
66 | |
67 /*********** MEMORY BANKS ***********/ | |
68 /* array of memory bank */ | |
69 static T_RVF_MB rvf_banks[RVF_MAX_REAL_MB]; | |
70 | |
71 /* array of waiting buffers */ | |
72 static T_RVF_BUFFER * waiting_buffers[RVF_MAX_WAITING_BUF]; | |
73 static UINT16 next_buffer[RVF_MAX_WAITING_BUF]; | |
74 static UINT16 first_free_element; | |
75 | |
76 /* array of memory bank name and id*/ | |
77 static T_RVF_MB_NAME_ID rvf_name_id[RVF_MAX_TOTAL_MB] = RVF_MB_MAPPING; | |
78 | |
79 | |
80 /* variable for statistics */ | |
81 #if RVF_ENABLE_STATS | |
82 static UINT32 required_size = 0; | |
83 static UINT32 obtained_size = 0; | |
84 static UINT32 used_size = 0; | |
85 static UINT32 mem_in_use = 0; | |
86 #endif | |
87 | |
88 /* lists of free buffers */ | |
89 static T_RVF_INTERNAL_BUF * lists[RVF_NB_FREE_LISTS]; | |
90 | |
91 /* last split-off buffer */ | |
92 T_RVF_INTERNAL_BUF * last_remainder = NULL; | |
93 | |
94 /* allocated static buffer pools */ | |
95 extern UINT8 Buf0[]; | |
96 extern UINT8 Buf1[]; | |
97 | |
98 /********Internal windows function used to display memory status *******/ | |
99 #ifdef _WINDOWS | |
100 extern void AddNewState(void *s,char *name, | |
101 unsigned long current,unsigned long peak, | |
102 unsigned long water,unsigned long bank); | |
103 #endif | |
104 | |
105 | |
106 /******************************************************************************* | |
107 ** | |
108 ** Function _rvf_init_free_queue | |
109 ** | |
110 ** Description Function called at startup to initialize a free | |
111 ** pool (statically or dynamically allocated). | |
112 ** It is called once for each free pool. | |
113 ** | |
114 ** Returns void | |
115 ** | |
116 *******************************************************************************/ | |
117 void _rvf_init_free_queue (UINT8 id, UINT32 size, void *p_mem) | |
118 { | |
119 T_RVF_INTERNAL_BUF *hdr; | |
120 UINT8 list_idx; | |
121 | |
122 /* round to up size to a multiple of 4 */ | |
123 size = (size + 3) & ~0x0003; | |
124 | |
125 /* store pool start address and size */ | |
126 _rvf_pools[id].start_address = p_mem; | |
127 | |
128 _rvf_pools[id].pool_size = size; | |
129 | |
130 /* Initialize the pool as a big free buffer */ | |
131 hdr = (T_RVF_INTERNAL_BUF *) p_mem; | |
132 hdr->buf_size = size - sizeof(T_RVF_INTERNAL_BUF) - sizeof(UINT32); /* last 4 bytes of the pool losts*/ | |
133 hdr->header.p_prev = NULL; | |
134 RVF_SET_PREV_IN_USE(hdr); | |
135 | |
136 NEXTCHUNK(hdr)->buf_size = 0; | |
137 | |
138 ENDSIZE(hdr) = hdr->buf_size; | |
139 | |
140 | |
141 /* get the corresponding list and insert the buffer */ | |
142 list_idx = RVF_BUF_LIST_INDEX( hdr->buf_size); | |
143 hdr->p_next = lists[list_idx]; | |
144 lists[list_idx] = hdr; | |
145 | |
146 last_remainder = hdr; | |
147 | |
148 } | |
149 | |
150 void rvf_mbox_buffer_init(T_RVF_RT_ADDR_ID_DATA* pRtAddrIdElement) { | |
151 UINT8 task_num, mbox_num; | |
152 /* Initialize all mailboxes queues of all tasks*/ | |
153 for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++) { | |
154 for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++) { | |
155 pRtAddrIdElement->OSTaskQFirst[mbox_num] = NULL; | |
156 pRtAddrIdElement->OSTaskQLast[mbox_num] = NULL; | |
157 } | |
158 } | |
159 } | |
160 /******************************************************************************* | |
161 ** | |
162 ** Function _rvf_buffer_init | |
163 ** | |
164 ** Description Called once internally by rvf at startup to initialize all | |
165 ** buffers and free buffer pools. | |
166 ** | |
167 ** Returns void | |
168 ** | |
169 *******************************************************************************/ | |
170 void _rvf_buffer_init(void) | |
171 { | |
172 UINT8 list_num; | |
173 UINT16 memory_bank_num; | |
174 | |
175 /* Initialize all mailboxes queues of all tasks*/ | |
176 /* for (task_num = 0; task_num < MAX_RVF_TASKS; task_num++) | |
177 { | |
178 for (mbox_num = 0; mbox_num < RVF_NUM_TASK_MBOX; mbox_num++) | |
179 { | |
180 OSTaskQFirst[task_num][mbox_num] = NULL; | |
181 OSTaskQLast [task_num][mbox_num] = NULL; | |
182 //pRtAddrIdTable[task_num]->OSTaskQFirst[mbox_num] = NULL; // only if static | |
183 //pRtAddrIdTable[task_num]->OSTaskQLast[mbox_num] = NULL; // only if static | |
184 } | |
185 } */ | |
186 | |
187 /* initialize free lists */ | |
188 for (list_num = 0; list_num < RVF_NB_FREE_LISTS; list_num++) | |
189 { | |
190 lists[list_num] = NULL; | |
191 } | |
192 | |
193 | |
194 /* initialize buffer pools */ | |
195 _rvf_init_mem_pool(); | |
196 | |
197 /* Initialize real memory banks */ | |
198 for (memory_bank_num = 0; memory_bank_num < RVF_MAX_REAL_MB; memory_bank_num++) | |
199 { | |
200 rvf_banks[memory_bank_num].cur_memory_used = 0; | |
201 rvf_banks[memory_bank_num].watermark = 0; | |
202 rvf_banks[memory_bank_num].max = 0; | |
203 rvf_banks[memory_bank_num].first_buffer_index = RVF_INVALID_INDEX; | |
204 rvf_banks[memory_bank_num].last_buffer_index = RVF_INVALID_INDEX; | |
205 rvf_banks[memory_bank_num].func = 0; | |
206 rvf_banks[memory_bank_num].returned_red = FALSE; | |
207 #if RVF_ENABLE_STATS | |
208 rvf_banks[memory_bank_num].max_reached = 0; | |
209 rvf_banks[memory_bank_num].required_size = 0; | |
210 rvf_banks[memory_bank_num].num_buf = 0; | |
211 #endif | |
212 } | |
213 | |
214 /* Initialize total memory banks */ | |
215 for (memory_bank_num = 0; memory_bank_num < RVF_MAX_TOTAL_MB; memory_bank_num++) | |
216 { | |
217 rvf_name_id[memory_bank_num].mb_params.size = 0; | |
218 rvf_name_id[memory_bank_num].mb_params.watermark = 0; | |
219 } | |
220 | |
221 | |
222 /* initialize array of waiting buffers */ | |
223 first_free_element = 0; | |
224 for( memory_bank_num = 0; memory_bank_num < RVF_MAX_WAITING_BUF; memory_bank_num++) | |
225 { waiting_buffers[memory_bank_num] = NULL; | |
226 next_buffer[memory_bank_num] = memory_bank_num + 1; | |
227 } | |
228 next_buffer[RVF_MAX_WAITING_BUF-1] = RVF_INVALID_INDEX; | |
229 } | |
230 | |
231 /******************************************************************************* | |
232 ** | |
233 ** Function _rvf_send_msg_to_mbox | |
234 ** | |
235 ** Description Called by applications to send a buffer to a SWE. | |
236 ** (Temporary internal use - DO NOT USE IT !) | |
237 ** (Presently, only for Christophe ) | |
238 ** Returns RVF_OK if successful, else an error code. | |
239 ** | |
240 *******************************************************************************/ | |
241 T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_G_ADDR_ID addr_id, UINT8 mbox,void *msg){ | |
242 return rvf_adapt_send_msg(addr_id, msg, mbox); | |
243 } | |
244 | |
245 /*T_RVF_RET _rvf_send_msg_to_mbox (T_RVF_ADDR_ID addr_id, UINT8 mbox,void *msg) | |
246 { | |
247 T_RVF_INTERNAL_BUF *p_hdr; | |
248 UINT8 task_id = (UINT8)addr_id; | |
249 | |
250 | |
251 if ((task_id >= MAX_RVF_TASKS) ) | |
252 { | |
253 rvf_send_trace( "RVF: rvf_send_msg(): invalid taskid", 35, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
254 rvf_free_buf (msg); | |
255 return RVF_INVALID_PARAMETER; | |
256 } | |
257 | |
258 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
259 | |
260 if (_rvf_chk_buf_damage(msg) == TRUE) | |
261 { rvf_send_trace( "RVF: rvf_send_msg(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
262 } | |
263 #endif | |
264 | |
265 | |
266 ((T_RV_HDR *)msg)->dest_addr_id = addr_id; | |
267 p_hdr = USER2MEM(msg); | |
268 | |
269 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
270 | |
271 if ( RVF_BUF_IS_LINKED( p_hdr) ) | |
272 { | |
273 rvf_send_trace( "RVF: rvf_send_msg(): buffer already enqueued", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
274 return RVF_MEMORY_ERR; | |
275 } | |
276 #endif | |
277 | |
278 rvf_disable(8); | |
279 | |
280 | |
281 if (OSTaskQFirst[task_id][mbox]) | |
282 { OSTaskQLast[task_id][mbox]->p_next = p_hdr; | |
283 } | |
284 else | |
285 { OSTaskQFirst[task_id][mbox] = p_hdr; | |
286 } | |
287 OSTaskQLast[task_id][mbox] = p_hdr; | |
288 | |
289 p_hdr->p_next = NULL; | |
290 | |
291 if (pRtAddrIdTable[task_id]->OSTaskQFirst[mbox]) { | |
292 pRtAddrIdTable[task_id]->OSTaskQLast[mbox]->p_next = p_hdr; | |
293 } else { | |
294 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr; | |
295 } | |
296 pRtAddrIdTable[task_id]->OSTaskQLast[mbox] = p_hdr; | |
297 | |
298 p_hdr->p_next = NULL; | |
299 | |
300 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
301 RVF_SET_BUF_LINKED(p_hdr); | |
302 #endif | |
303 | |
304 rvf_enable(); | |
305 | |
306 rvf_send_event(task_id, (UINT16) (EVENT_MASK(mbox)) ); | |
307 return RVF_OK; | |
308 }*/ | |
309 | |
310 /******************************************************************************* | |
311 ** | |
312 ** Function rvf_read_mbox | |
313 ** | |
314 ** Description Called by applications to read a buffer from one of | |
315 ** the task mailboxes. | |
316 ** | |
317 ** Returns NULL if the mailbox was empty, else the address of a buffer | |
318 ** | |
319 *******************************************************************************/ | |
320 void * rvf_read_mbox (UINT8 mbox) { | |
321 T_RVF_G_ADDR_ID task_id = rvf_get_taskid(); | |
322 | |
323 return rvf_read_addr_mbox (task_id, mbox) ; | |
324 } | |
325 void * rvf_read_addr_mbox (T_RVF_G_ADDR_ID task_id, UINT8 mbox) { | |
326 void * p_buf = NULL; | |
327 T_RVF_INTERNAL_BUF * p_hdr; | |
328 | |
329 mbox=resolveHostAddrId(mbox); | |
330 | |
331 if ((task_id >= MAX_RVF_TASKS) || (mbox >= RVF_NUM_TASK_MBOX)) | |
332 { rvf_send_trace( "RVF: rvf_read_mbox(): invalid taskid or mbox", 44, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
333 return NULL; | |
334 } | |
335 | |
336 rvf_disable(9); /* enter critical section */ | |
337 | |
338 /* if the chained list is not empty */ | |
339 /*if ( OSTaskQFirst[task_id][mbox] ) | |
340 { p_hdr = OSTaskQFirst[task_id][mbox]; | |
341 OSTaskQFirst[task_id][mbox] = p_hdr->p_next; | |
342 | |
343 p_hdr->p_next = NULL;*/ | |
344 if ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] ) { | |
345 p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox]; | |
346 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox] = p_hdr->p_next; | |
347 | |
348 p_hdr->p_next = NULL; | |
349 | |
350 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
351 RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */ | |
352 #endif | |
353 p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
354 } | |
355 | |
356 rvf_enable(); /* exit critical section */ | |
357 | |
358 return (p_buf); | |
359 } | |
360 | |
361 /******************************************************************************* | |
362 ** | |
363 ** Function rvf_enqueue | |
364 ** | |
365 ** Description Enqueue a buffer at the tail of the queue | |
366 ** | |
367 ** Returns RVF_OK if successful, else an error code. | |
368 ** | |
369 *******************************************************************************/ | |
370 T_RVF_RET rvf_enqueue (T_RVF_BUFFER_Q *p_q, void *p_buf) | |
371 { | |
372 T_RVF_INTERNAL_BUF *p_hdr; | |
373 | |
374 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
375 if ( _rvf_chk_buf_damage(p_buf) ) | |
376 { rvf_send_trace( "RVF: rvf_enqueue(): buffer corrupted", 36, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID); | |
377 } | |
378 #endif | |
379 | |
380 /* check if the buffer has been already enqueued */ | |
381 p_hdr = USER2MEM(p_buf); | |
382 | |
383 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
384 if( RVF_BUF_IS_LINKED(p_hdr) ) | |
385 { | |
386 rvf_send_trace( "RVF: rvf_enqueue(): buffer already enqueued", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID); | |
387 return RVF_MEMORY_ERR; | |
388 } | |
389 #endif | |
390 | |
391 rvf_disable(10); /* enter critical section */ | |
392 | |
393 /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */ | |
394 /* p_q->p_last and p_q->p_first point to the user buffer, since p_hdr->p_next points to the T_RVF_INTERNAL_BUF */ | |
395 if (p_q->p_first) /* if the queue is not empty */ | |
396 { | |
397 T_RVF_INTERNAL_BUF * p_last_hdr = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_q->p_last - sizeof(T_RVF_INTERNAL_BUF) ); | |
398 p_last_hdr->p_next = p_hdr; | |
399 } | |
400 else | |
401 p_q->p_first = p_buf; | |
402 | |
403 p_q->p_last = p_buf; | |
404 p_q->count++; | |
405 | |
406 p_hdr->p_next = NULL; | |
407 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
408 RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */ | |
409 #endif | |
410 | |
411 rvf_enable(); /* exit critical section */ | |
412 return RVF_OK; | |
413 } | |
414 | |
415 | |
416 | |
417 /******************************************************************************* | |
418 ** | |
419 ** Function rvf_dequeue | |
420 ** | |
421 ** Description Dequeue a buffer from the head of a queue | |
422 ** | |
423 ** Returns NULL if queue is empty, else buffer | |
424 ** | |
425 *******************************************************************************/ | |
426 void * rvf_dequeue (T_RVF_BUFFER_Q *p_q) | |
427 { | |
428 T_RVF_INTERNAL_BUF *p_hdr; | |
429 | |
430 if (!p_q->count) /* if the queue is empty */ | |
431 return (NULL); | |
432 | |
433 rvf_disable(12); /* enter critical section */ | |
434 | |
435 p_hdr = USER2MEM(p_q->p_first ); | |
436 | |
437 | |
438 /* Keep buffers such that RVF header is invisible */ | |
439 if (p_hdr->p_next) | |
440 p_q->p_first = ((UINT8 *)p_hdr->p_next + sizeof(T_RVF_INTERNAL_BUF)); | |
441 else | |
442 { | |
443 p_q->p_first = NULL; | |
444 p_q->p_last = NULL; | |
445 } | |
446 | |
447 p_q->count--; | |
448 | |
449 p_hdr->p_next = NULL; | |
450 | |
451 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
452 RVF_SET_BUF_UNLINKED(p_hdr); /* change buffer status */ | |
453 #endif | |
454 | |
455 rvf_enable(); /* exit critical section */ | |
456 | |
457 return (MEM2USER(p_hdr) ); | |
458 } | |
459 | |
460 | |
461 | |
462 /******************************************************************************* | |
463 ** | |
464 ** Function rvf_enqueue_head | |
465 ** | |
466 ** Description Enqueue a buffer at the head of the queue | |
467 ** | |
468 ** Returns RVF_OK if successful, else an error code. | |
469 ** | |
470 *******************************************************************************/ | |
471 T_RVF_RET rvf_enqueue_head (T_RVF_BUFFER_Q *p_q, void *p_buf) | |
472 { | |
473 T_RVF_INTERNAL_BUF *p_hdr; | |
474 | |
475 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
476 if ( _rvf_chk_buf_damage(p_buf) ) | |
477 { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer corrupted", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
478 } | |
479 #endif | |
480 | |
481 p_hdr = USER2MEM(p_buf); | |
482 | |
483 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
484 if( RVF_BUF_IS_LINKED(p_hdr) ) | |
485 { rvf_send_trace( "RVF: rvf_enqueue_head(): buffer already enqueued", 48, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
486 return RVF_MEMORY_ERR; | |
487 } | |
488 #endif | |
489 | |
490 rvf_disable(11); /* enter critical section */ | |
491 | |
492 if (p_q->p_first) /* if the queue is not empty */ | |
493 { p_hdr->p_next = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_q->p_first - sizeof(T_RVF_INTERNAL_BUF) ); | |
494 p_q->p_first = p_buf; | |
495 } | |
496 else | |
497 { p_q->p_first = p_buf; | |
498 p_q->p_last = p_buf; | |
499 p_hdr->p_next = NULL; | |
500 } | |
501 p_q->count++; | |
502 | |
503 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
504 RVF_SET_BUF_LINKED(p_hdr); /* change buffer status */ | |
505 #endif | |
506 | |
507 | |
508 rvf_enable(); /* exit critical section */ | |
509 | |
510 return RVF_OK; | |
511 } | |
512 | |
513 | |
514 | |
515 /******************************************************************************* | |
516 ** | |
517 ** Function rvf_get_buf_size | |
518 ** | |
519 ** Description Called by an application to get the size of a buffer. | |
520 ** | |
521 ** Returns the size of the buffer or 0 if the address is invalid. | |
522 ** | |
523 *******************************************************************************/ | |
524 INLINE UINT32 rvf_get_buf_size (void *bptr) | |
525 { | |
526 T_RVF_INTERNAL_BUF *p_hdr; | |
527 | |
528 p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *) bptr - sizeof(T_RVF_INTERNAL_BUF) ); | |
529 | |
530 if ((UINT32)p_hdr & 1) return 0; /* invalid pointer: odd address*/ | |
531 | |
532 return (GETSIZE(p_hdr) - RVF_CORRUPT_OVERHEAD) ; | |
533 } | |
534 | |
535 | |
536 /******************************************************************************* | |
537 ** | |
538 ** Function _rvf_chk_buf_damage | |
539 ** | |
540 ** Description Called internally by rvf to check for buffer corruption. | |
541 ** | |
542 ** Returns TRUE if there is a problem, else FALSE | |
543 ** | |
544 *******************************************************************************/ | |
545 #if RVF_ENABLE_BUF_CORRUPTION_CHECK | |
546 BOOLEAN _rvf_chk_buf_damage(void *bptr) | |
547 { | |
548 UINT32 *lg; | |
549 T_RVF_INTERNAL_BUF * p_hdr; | |
550 | |
551 if((UINT32)bptr & 1) /* odd address */ | |
552 { return TRUE; | |
553 } | |
554 | |
555 p_hdr = USER2MEM(bptr); /* get the internal header */ | |
556 | |
557 lg = (UINT32*)( (UINT8*)bptr + GETSIZE(p_hdr) - sizeof(UINT32) ); | |
558 | |
559 if (lg == 0) | |
560 return TRUE; | |
561 | |
562 if(*lg == GETSIZE(p_hdr) ) | |
563 { | |
564 return FALSE; | |
565 } | |
566 return TRUE; | |
567 } | |
568 #endif | |
569 | |
570 | |
571 | |
572 /******************************************************************************* | |
573 ** | |
574 ** Function _find_buf | |
575 ** | |
576 ** Description Internal function which is in charge of finding a free buffer | |
577 ** of the requested size in one of the lists. | |
578 ** | |
579 ** Returns A pointer to the buffer header, or NULL if none available | |
580 ** | |
581 *******************************************************************************/ | |
582 INLINE void * _find_buf (UINT32 size) | |
583 { | |
584 T_RVF_INTERNAL_BUF * p_hdr; | |
585 UINT8 idx; | |
586 | |
587 if (size == 0) /* if user requires a 0 byte buffer !! */ | |
588 { return (NULL); | |
589 } | |
590 | |
591 /* add the overhead for buffer corruption check */ | |
592 size = REQ2SIZE(size); | |
593 | |
594 /* find the corresponding list */ | |
595 idx = RVF_BUF_LIST_INDEX(size); | |
596 | |
597 /* 1. try in the bin corresponding to the requested size. */ | |
598 /* 2. try to use the last_remainder chunk. */ | |
599 /* 3. try in the others bins of greater size. */ | |
600 | |
601 if( (lists[idx] == NULL) || ( GETSIZE(lists[idx]) < size) ) | |
602 /* if the first buffer in the appropriate bin is not big enough. */ | |
603 { | |
604 rvf_disable(4); /* enter critical section */ | |
605 | |
606 if( last_remainder != NULL) | |
607 { | |
608 p_hdr = last_remainder; | |
609 | |
610 /* if the last remainder is big enough */ | |
611 if( GETSIZE(p_hdr) >= size ) | |
612 { | |
613 | |
614 if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */ | |
615 { /* create a new free buffer and link it in the appropriate list*/ | |
616 | |
617 T_RVF_INTERNAL_BUF * new_buf; | |
618 UINT8 new_idx; | |
619 | |
620 new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF)); | |
621 new_buf->buf_size = GETSIZE(p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF); | |
622 ENDSIZE(new_buf) = new_buf->buf_size; | |
623 | |
624 /* remove the used buffer from the list */ | |
625 if( p_hdr->header.p_prev != NULL) | |
626 { (p_hdr->header.p_prev)->p_next = p_hdr->p_next; | |
627 } | |
628 else | |
629 { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next; | |
630 } | |
631 if( p_hdr->p_next != NULL) | |
632 { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev; | |
633 } | |
634 p_hdr->p_next = NULL; | |
635 | |
636 SETSIZE(p_hdr, size); | |
637 ENDSIZE(p_hdr) = size; /* to CHANGE */ | |
638 | |
639 /* insert the new buffer in the appropriate list */ | |
640 new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size); | |
641 new_buf->p_next = lists[new_idx]; | |
642 lists[new_idx] = new_buf; | |
643 new_buf->header.p_prev = NULL; | |
644 if( new_buf->p_next != NULL) | |
645 { (new_buf->p_next)->header.p_prev = new_buf; | |
646 } | |
647 RVF_SET_PREV_IN_USE(new_buf); | |
648 | |
649 last_remainder = new_buf; | |
650 | |
651 rvf_enable(); /* exit critical section */ | |
652 return p_hdr; | |
653 | |
654 } | |
655 else /* return the entire buffer */ | |
656 { | |
657 /* remove the used buffer from the list */ | |
658 if( p_hdr->header.p_prev != NULL) | |
659 { (p_hdr->header.p_prev)->p_next = p_hdr->p_next; | |
660 } | |
661 else | |
662 { lists[ RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) )] = p_hdr->p_next; | |
663 } | |
664 if( p_hdr->p_next != NULL) | |
665 { (p_hdr->p_next)->header.p_prev = p_hdr->header.p_prev; | |
666 } | |
667 p_hdr->p_next = NULL; | |
668 | |
669 RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) ); | |
670 | |
671 last_remainder = NULL; | |
672 | |
673 rvf_enable(); /* exit critical section */ | |
674 return p_hdr; | |
675 } | |
676 } | |
677 else /* the last remainder is too small */ | |
678 { | |
679 /* clear the last remainder */ | |
680 last_remainder = NULL; | |
681 } | |
682 | |
683 } | |
684 rvf_enable(); /* exit critical section */ | |
685 } | |
686 | |
687 while( idx < RVF_NB_FREE_LISTS ) | |
688 { | |
689 rvf_disable(4); /* enter critical section */ | |
690 | |
691 if( lists[idx] != NULL ) /*if the list is not empty */ | |
692 { /* remove the first buffer from the list */ | |
693 | |
694 p_hdr = lists[idx]; | |
695 if( GETSIZE(p_hdr) >= size) | |
696 { | |
697 if( GETSIZE(p_hdr) >= (size + RVF_MIN_USABLE_SIZE ) ) /* if the free part may be used */ | |
698 { /* create a new free buffer and link it in the appropriate list*/ | |
699 | |
700 T_RVF_INTERNAL_BUF * new_buf; | |
701 UINT8 new_idx; | |
702 | |
703 new_buf = (T_RVF_INTERNAL_BUF *) ((UINT8*)p_hdr + size + sizeof(T_RVF_INTERNAL_BUF)); | |
704 new_buf->buf_size = GETSIZE( p_hdr) - size - sizeof(T_RVF_INTERNAL_BUF); | |
705 ENDSIZE(new_buf) = new_buf->buf_size; | |
706 | |
707 /* remove the used buffer from the list */ | |
708 lists[idx] = p_hdr->p_next; | |
709 if( p_hdr->p_next != NULL) | |
710 { (p_hdr->p_next)->header.p_prev = NULL; | |
711 } | |
712 p_hdr->p_next = NULL; | |
713 | |
714 SETSIZE(p_hdr, size); | |
715 ENDSIZE(p_hdr) = size; | |
716 | |
717 /* insert the new buffer in the appropriate list */ | |
718 new_idx = RVF_BUF_LIST_INDEX(new_buf->buf_size); | |
719 new_buf->p_next = lists[new_idx]; | |
720 lists[new_idx] = new_buf; | |
721 new_buf->header.p_prev = NULL; | |
722 if( new_buf->p_next != NULL) | |
723 { (new_buf->p_next)->header.p_prev = new_buf; | |
724 } | |
725 RVF_SET_PREV_IN_USE(new_buf); | |
726 | |
727 last_remainder = new_buf; /* set this new buffer as the last remainder */ | |
728 | |
729 rvf_enable(); /* exit critical section */ | |
730 return p_hdr; | |
731 | |
732 } | |
733 else /* return the entire buffer */ | |
734 { lists[idx] = p_hdr->p_next; | |
735 if( p_hdr->p_next != NULL) | |
736 { (p_hdr->p_next)->header.p_prev = NULL; | |
737 } | |
738 p_hdr->p_next = NULL; | |
739 RVF_SET_PREV_IN_USE( NEXTCHUNK(p_hdr) ); | |
740 | |
741 if( last_remainder == p_hdr) /* if it was the last_remainder, clear it. */ | |
742 { | |
743 last_remainder = NULL; | |
744 } | |
745 | |
746 rvf_enable(); /* exit critical section */ | |
747 return p_hdr; | |
748 } | |
749 } | |
750 } | |
751 | |
752 rvf_enable(); /* exit critical section */ | |
753 | |
754 idx++; /* search in the next list */ | |
755 } | |
756 | |
757 return NULL; | |
758 } | |
759 | |
760 | |
761 /******************************************************************************* | |
762 ** | |
763 ** Function _release_buf | |
764 ** | |
765 ** Description Internal function called to release a buffer after use. | |
766 ** The parameter points to the beginning of the header. | |
767 ** | |
768 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
769 ** | |
770 *******************************************************************************/ | |
771 INLINE BOOLEAN _release_buf (T_RVF_INTERNAL_BUF *p_hdr) | |
772 { UINT8 idx; | |
773 | |
774 #if RVF_ENABLE_BUF_CORRUPTION_CHECK /* check for buffer corruption:i.e. if user wrote data after the end of the buffer */ | |
775 if ( _rvf_chk_buf_damage( MEM2USER(p_hdr) ) ) | |
776 { rvf_send_trace( "RVF: _release_buf(): buffer corrupted", 37, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
777 return FALSE; | |
778 } | |
779 | |
780 /* check if the buffer has been already freed */ | |
781 if ( RVF_IS_PREV_FREE( NEXTCHUNK(p_hdr) ) ) /* check buffer status */ | |
782 { rvf_send_trace( "RVF: _release_buf(): buffer already freed", 41, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
783 return FALSE; | |
784 } | |
785 | |
786 #endif | |
787 | |
788 #if RVF_ENABLE_BUF_LINKAGE_CHECK /* check for buffer linkage */ | |
789 if ( RVF_BUF_IS_LINKED(p_hdr) ) /* check buffer status */ | |
790 { rvf_send_trace( "RVF: _release_buf(): free buf buffer linked", 43, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
791 return FALSE; | |
792 } | |
793 #endif | |
794 | |
795 | |
796 rvf_disable(6); /* enter critical section */ | |
797 | |
798 /* try to coalesce the buffer with its neighbors (left and right) */ | |
799 | |
800 if( RVF_IS_PREV_FREE(p_hdr) ) | |
801 { /* merge the buffer with its left neighbor */ | |
802 UINT32 left_buf_size = *((UINT32*)((UINT8*)p_hdr - sizeof(UINT32) ) ); | |
803 T_RVF_INTERNAL_BUF * left_buf = (T_RVF_INTERNAL_BUF *) ((UINT8 *)p_hdr - left_buf_size - sizeof(T_RVF_INTERNAL_BUF) ); | |
804 | |
805 /* remove the left buffer from its list */ | |
806 if( left_buf->header.p_prev == NULL) | |
807 { lists[ RVF_BUF_LIST_INDEX(left_buf_size)] = left_buf->p_next; | |
808 } | |
809 else | |
810 { (left_buf->header.p_prev)->p_next = left_buf->p_next; | |
811 } | |
812 if( left_buf->p_next != NULL) | |
813 { | |
814 (left_buf->p_next)->header.p_prev = left_buf->header.p_prev; | |
815 } | |
816 /* set the size of the newly created buffer */ | |
817 SETSIZE(left_buf, (left_buf_size + GETSIZE(p_hdr) + sizeof(T_RVF_INTERNAL_BUF) ) ); | |
818 /* set the current buffer as free to allow check for double free */ | |
819 RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) ); | |
820 | |
821 p_hdr = left_buf; | |
822 } | |
823 | |
824 /* check for pool limits */ | |
825 if( GETSIZE( NEXTCHUNK(p_hdr) ) != 0) | |
826 { T_RVF_INTERNAL_BUF * right_buf = NEXTCHUNK(p_hdr); | |
827 /* merge the buffer with its right neighbor */ | |
828 | |
829 if( RVF_IS_PREV_FREE( NEXTCHUNK(right_buf) ) ) | |
830 { /* remove the right buffer from its list */ | |
831 UINT32 right_buf_size = GETSIZE( right_buf); | |
832 | |
833 if( right_buf->header.p_prev == NULL) | |
834 { lists[ RVF_BUF_LIST_INDEX(right_buf_size)] = right_buf->p_next; | |
835 } | |
836 else | |
837 { (right_buf->header.p_prev)->p_next = right_buf->p_next; | |
838 } | |
839 if( right_buf->p_next != NULL) | |
840 { (right_buf->p_next)->header.p_prev = right_buf->header.p_prev; | |
841 } | |
842 | |
843 right_buf_size += GETSIZE(p_hdr); | |
844 SETSIZE(p_hdr, (right_buf_size + sizeof(T_RVF_INTERNAL_BUF) ) ); | |
845 | |
846 if( last_remainder == right_buf) /* keep as last_remainder */ | |
847 { last_remainder = p_hdr; | |
848 } | |
849 } | |
850 } | |
851 | |
852 /* enqueue the free buffer in the appropriate list */ | |
853 idx = RVF_BUF_LIST_INDEX( GETSIZE(p_hdr) ); | |
854 p_hdr->header.p_prev = NULL; | |
855 p_hdr->p_next = lists[idx]; | |
856 lists[idx] = p_hdr; | |
857 if( p_hdr->p_next != NULL) | |
858 { (p_hdr->p_next)->header.p_prev = p_hdr; | |
859 } | |
860 | |
861 ENDSIZE(p_hdr) = GETSIZE(p_hdr); | |
862 RVF_SET_PREV_FREE( NEXTCHUNK(p_hdr) ); | |
863 | |
864 rvf_enable(); /* exit critical section */ | |
865 return TRUE; | |
866 } | |
867 | |
868 | |
869 /******************************************************************************* | |
870 ** Function _str_cmp | |
871 ** | |
872 ** Description Internal function which compares two null-terminated string. | |
873 ** Returns TRUE if they are equal, else FALSE. | |
874 *******************************************************************************/ | |
875 BOOLEAN _str_cmp( char *str1, char * str2) | |
876 { UINT8 i; | |
877 for ( i = 0; (str1[i] == str2[i]) && (str1[i] != 0) && (str2[i] != 0) && (i < RVF_MAX_MB_LEN); i++ ); | |
878 if ( i == RVF_MAX_MB_LEN) | |
879 { return TRUE; | |
880 } | |
881 | |
882 if ( (str1[i] == 0) && (str2[i] == 0) ) | |
883 { return TRUE; | |
884 } | |
885 return FALSE; | |
886 } | |
887 | |
888 /****************************************************************************** | |
889 ** | |
890 ** MEMORY BANK RELATED FUNCTIONS | |
891 ** | |
892 ******************************************************************************/ | |
893 | |
894 /******************************************************************************* | |
895 ** | |
896 ** Function _remove_from_list | |
897 ** | |
898 ** Description Internal function called to remove a buffer from the list of | |
899 ** buffer waiting to be counted on the memory bank. | |
900 ** The parameter points to the beginning of the header. | |
901 ** | |
902 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
903 ** | |
904 *******************************************************************************/ | |
905 BOOLEAN _remove_from_list (void *bptr, T_RVF_MB * mb) | |
906 { UINT16 * index; | |
907 UINT16 free_elem, prec; | |
908 | |
909 /* check all elements of the list */ | |
910 index = &(mb->first_buffer_index); | |
911 prec = RVF_INVALID_INDEX; | |
912 | |
913 while ( (*index != RVF_INVALID_INDEX) && (waiting_buffers[*index]!=bptr) ) | |
914 { prec = *index; | |
915 index = &(next_buffer[*index]); | |
916 } | |
917 | |
918 if (waiting_buffers[*index] == bptr) | |
919 { free_elem = *index; | |
920 *index = next_buffer[free_elem]; /* link preceding element to the next one */ | |
921 | |
922 if (next_buffer[free_elem] == RVF_INVALID_INDEX ) /* last element in the list */ | |
923 { mb->last_buffer_index = prec; | |
924 } | |
925 | |
926 waiting_buffers[free_elem] = NULL; | |
927 next_buffer[free_elem] = first_free_element; /* link free elements */ | |
928 first_free_element = free_elem; | |
929 return TRUE; | |
930 } | |
931 return FALSE; /* buffer not found */ | |
932 } | |
933 | |
934 | |
935 /******************************************************************************* | |
936 ** | |
937 ** Function _add_to_list | |
938 ** | |
939 ** Description Internal function called to add a buffer to the list of | |
940 ** buffer waiting to be counted on the memory bank. | |
941 ** The parameter points to the beginning of the header. | |
942 ** | |
943 ** Returns BOOLEAN: TRUE if successful, else FALSE | |
944 ** | |
945 *******************************************************************************/ | |
946 BOOLEAN _add_to_list (void *bptr, T_RVF_MB * mb) | |
947 { UINT16 index = first_free_element; | |
948 | |
949 first_free_element = next_buffer[index]; | |
950 | |
951 waiting_buffers[index] = bptr; | |
952 next_buffer[index] = RVF_INVALID_INDEX; | |
953 | |
954 if ( mb->last_buffer_index == RVF_INVALID_INDEX) /* empty list */ | |
955 { mb->first_buffer_index = index; | |
956 mb->last_buffer_index = index; | |
957 } | |
958 else | |
959 { next_buffer[mb->last_buffer_index] = index; | |
960 mb->last_buffer_index = index; | |
961 } | |
962 | |
963 return TRUE; | |
964 } | |
965 | |
966 | |
967 /******************************************************************************* | |
968 ** | |
969 ** Function rvf_create_mb | |
970 ** | |
971 ** Description Called by an application to create a memory bank | |
972 ** | |
973 ** Parameters: memory bank name, memory bank param | |
974 ** (return) memory bank id | |
975 ** | |
976 ** Returns T_RVF_RET: RVF_OK if success | |
977 ** | |
978 *******************************************************************************/ | |
979 T_RVF_RET rvf_create_mb(T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM mb_param, T_RVF_MB_ID *mb_id) | |
980 { UINT8 num_mb; | |
981 T_RVF_MB * mb; | |
982 UINT32 available_mem = 0; | |
983 UINT32 required_mem = 0; | |
984 | |
985 /* find the mb name in the array */ | |
986 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
987 | |
988 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
989 { | |
990 /* DLC added for dynamic memory bank creation*/ | |
991 | |
992 /* search the first available place in the array */ | |
993 T_RVF_MB_ID first_available_mb_id = 0; | |
994 BOOLEAN mb_id_found = FALSE; | |
995 | |
996 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) ; num_mb++) | |
997 { if( rvf_name_id[num_mb].mb_id == first_available_mb_id) | |
998 { first_available_mb_id ++; | |
999 } | |
1000 } | |
1001 | |
1002 while( (first_available_mb_id < RVF_MAX_REAL_MB) && (mb_id_found == FALSE) ) | |
1003 { | |
1004 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (rvf_name_id[num_mb].mb_name[0] != 0) && (rvf_name_id[num_mb].mb_id != first_available_mb_id) ; num_mb++); | |
1005 if ( rvf_name_id[num_mb].mb_id != first_available_mb_id) | |
1006 { /* available mb id found */ | |
1007 mb_id_found = TRUE; | |
1008 } | |
1009 else | |
1010 { /* try the next one */ | |
1011 first_available_mb_id++; | |
1012 } | |
1013 } | |
1014 | |
1015 if ( (num_mb == RVF_MAX_TOTAL_MB) || (first_available_mb_id + 1 >= RVF_MAX_REAL_MB ) ) /* no available space in the array */ | |
1016 | |
1017 { *mb_id = RVF_INVALID_MB_ID; | |
1018 return RVF_INVALID_PARAMETER; | |
1019 } | |
1020 | |
1021 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */ | |
1022 | |
1023 /* create the new mb name and id */ | |
1024 strcpy( rvf_name_id[num_mb].mb_name, mb_name); | |
1025 rvf_name_id[num_mb].mb_id = first_available_mb_id; | |
1026 | |
1027 /* initialize the next one */ | |
1028 rvf_name_id[num_mb+1].mb_name[0] = 0; | |
1029 rvf_name_id[num_mb+1].mb_id = 0; | |
1030 | |
1031 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */ | |
1032 } | |
1033 | |
1034 /* check if the memory bank has been already created */ | |
1035 if ( rvf_name_id[ num_mb].mb_params.size != 0) | |
1036 { *mb_id = RVF_INVALID_MB_ID; | |
1037 return RVF_INTERNAL_ERR; | |
1038 } | |
1039 | |
1040 rvf_get_available_mem( &available_mem, &required_mem); | |
1041 | |
1042 if ( ( (required_mem + mb_param.size)*100) > ( available_mem * _rvf_get_mem_usage_ratio()) ) /* if there is not enough available memory to create this mb */ | |
1043 { *mb_id = RVF_INVALID_MB_ID; /* In a next version: try to create a dynamic pool */ | |
1044 return RVF_MEMORY_ERR; | |
1045 } | |
1046 | |
1047 rvf_disable(20); /* enter critical section */ | |
1048 | |
1049 /* save the mb parameters for deletion */ | |
1050 rvf_name_id[num_mb].mb_params.size = mb_param.size; | |
1051 rvf_name_id[num_mb].mb_params.watermark = mb_param.watermark; | |
1052 | |
1053 * mb_id = rvf_name_id[num_mb].mb_id; | |
1054 mb = &rvf_banks[ *mb_id ]; | |
1055 /* initialize the memory bank structure */ | |
1056 mb->watermark += mb_param.watermark; | |
1057 mb->max += mb_param.size; | |
1058 | |
1059 rvf_enable(); /* exit critical section */ | |
1060 | |
1061 return RVF_OK; | |
1062 } | |
1063 | |
1064 | |
1065 /******************************************************************************* | |
1066 ** | |
1067 ** Function rvf_get_mb_id | |
1068 ** | |
1069 ** Description Called by an application to get the memory bank id from its name | |
1070 ** | |
1071 ** Parameters: memory bank name | |
1072 ** (return) memory bank id | |
1073 ** | |
1074 ** Returns T_RVF_RET: RVF_OK if success | |
1075 ** | |
1076 *******************************************************************************/ | |
1077 T_RVF_RET rvf_get_mb_id(T_RVF_MB_NAME mb_name, T_RVF_MB_ID *mb_id) | |
1078 { UINT8 num_mb; | |
1079 | |
1080 | |
1081 /* find the mb name in the array */ | |
1082 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1083 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1084 { *mb_id = RVF_INVALID_MB_ID; | |
1085 return RVF_INVALID_PARAMETER; | |
1086 } | |
1087 if ( rvf_banks[ rvf_name_id[num_mb].mb_id ].max == 0 ) | |
1088 { /* the memory bank has not been created */ | |
1089 *mb_id = RVF_INVALID_MB_ID; | |
1090 return RVF_NOT_READY; | |
1091 } | |
1092 *mb_id = rvf_name_id[num_mb].mb_id; | |
1093 return RVF_OK; | |
1094 } | |
1095 | |
1096 | |
1097 /******************************************************************************* | |
1098 ** | |
1099 ** Function rvf_delete_mb | |
1100 ** | |
1101 ** Description Called by an application to delete a memory bank | |
1102 ** | |
1103 ** Parameters: memory bank name | |
1104 ** | |
1105 ** Returns T_RVF_RET: RVF_OK if success | |
1106 ** | |
1107 *******************************************************************************/ | |
1108 T_RVF_RET rvf_delete_mb(T_RVF_MB_NAME mb_name) | |
1109 { UINT8 num_mb; | |
1110 T_RVF_MB * mb; | |
1111 | |
1112 /* find the mb name in the array */ | |
1113 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1114 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1115 { return RVF_INVALID_PARAMETER; | |
1116 } | |
1117 mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1118 | |
1119 /* check if the mb is used more than once or not */ | |
1120 if ( mb->max == rvf_name_id[num_mb].mb_params.size ) | |
1121 { /* mb is used only once, check if cur_memory_used > 0 */ | |
1122 if ( mb->cur_memory_used > 0) | |
1123 { rvf_send_trace( "RVF: rvf_delete_mb(): not all buffers have been freed", 53, NULL_PARAM, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
1124 return RVF_MEMORY_ERR; | |
1125 /* free all buffers ????? -> NOT POSSIBLE */ | |
1126 } | |
1127 /* initialize mb params */ | |
1128 mb->max = 0; | |
1129 mb->first_buffer_index = RVF_INVALID_INDEX; | |
1130 mb->last_buffer_index = RVF_INVALID_INDEX; | |
1131 mb->watermark = 0; | |
1132 mb->returned_red = FALSE; | |
1133 mb->func = 0; | |
1134 #if RVF_ENABLE_STATS | |
1135 mb->max_reached = 0; | |
1136 mb->required_size = 0; | |
1137 mb->num_buf = 0; | |
1138 #endif | |
1139 | |
1140 } | |
1141 else /* mb is still used by another entity */ | |
1142 { /* change mb params */ | |
1143 mb->max -= rvf_name_id[num_mb].mb_params.size; | |
1144 mb->watermark -= rvf_name_id[num_mb].mb_params.watermark; | |
1145 } | |
1146 | |
1147 rvf_name_id[num_mb].mb_params.size = 0; | |
1148 rvf_name_id[num_mb].mb_params.watermark = 0; | |
1149 | |
1150 return RVF_OK; | |
1151 } | |
1152 | |
1153 T_RVF_RET rvf_mb_is_used(T_RVF_MB_NAME mb_name, UINT8* isUsed) { | |
1154 UINT8 num_mb; | |
1155 T_RVF_MB * mb; | |
1156 | |
1157 *isUsed=0; | |
1158 | |
1159 /* find the mb name in the array */ | |
1160 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1161 if ( num_mb == RVF_MAX_TOTAL_MB ) {/* mb name not found */ | |
1162 return RVF_INVALID_PARAMETER; | |
1163 } | |
1164 mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1165 | |
1166 /* check if the mb is used more than once or not */ | |
1167 if ( mb->max == rvf_name_id[num_mb].mb_params.size ) { | |
1168 /* mb is used only once, check if cur_memory_used > 0 */ | |
1169 if ( mb->cur_memory_used > 0) *isUsed=1; | |
1170 } | |
1171 return RVF_OK; | |
1172 } | |
1173 | |
1174 | |
1175 | |
1176 /******************************************************************************* | |
1177 ** | |
1178 ** Function rvf_get_mb_status | |
1179 ** | |
1180 ** Description Called by an application to get the status of a memory bank | |
1181 ** | |
1182 ** Parameters: memory bank id | |
1183 ** | |
1184 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1185 ** RVF_YELLOW if watermark limit has been reached, | |
1186 ** RVF_RED if max size has been reached | |
1187 ** | |
1188 *******************************************************************************/ | |
1189 T_RVF_MB_STATUS rvf_get_mb_status(T_RVF_MB_ID mb_id) | |
1190 { T_RVF_MB * mb; | |
1191 | |
1192 /* checking for invalid memory bank IDs */ | |
1193 if (mb_id >= RVF_MAX_REAL_MB) | |
1194 { | |
1195 #ifdef RVM_DAR_SWE | |
1196 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1197 DAR_ASCII_FORMAT, | |
1198 RVM_USE_ID); | |
1199 #else | |
1200 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1201 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1202 NULL_PARAM, | |
1203 RV_TRACE_LEVEL_ERROR, | |
1204 RVM_USE_ID); | |
1205 #endif | |
1206 return RVF_RED; | |
1207 } | |
1208 mb = &rvf_banks[mb_id]; | |
1209 | |
1210 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1211 { return RVF_RED; | |
1212 } | |
1213 | |
1214 if ( mb->cur_memory_used < mb->watermark ) | |
1215 { return RVF_GREEN; | |
1216 } | |
1217 else | |
1218 { if ( mb->cur_memory_used < mb->max ) | |
1219 { return RVF_YELLOW; | |
1220 } | |
1221 else | |
1222 { return RVF_RED; /* since max and cur_memory_used are set to 0 for not-created mb, it will return RED*/ | |
1223 } | |
1224 } | |
1225 } | |
1226 | |
1227 /******************************************************************************* | |
1228 ** | |
1229 ** Function rvf_get_mb_unused_mem | |
1230 ** | |
1231 ** Description Called by an application to get the number of bytes available | |
1232 ** until the memory bank size. | |
1233 ** | |
1234 ** Parameters: memory bank id | |
1235 ** | |
1236 ** Returns UINT32: number of bytes available | |
1237 ** returns 0 if the memory bank has not been created. | |
1238 ** | |
1239 *******************************************************************************/ | |
1240 UINT32 rvf_get_mb_unused_mem(T_RVF_MB_ID mb_id) | |
1241 { T_RVF_MB * mb; | |
1242 mb = &rvf_banks[mb_id]; | |
1243 | |
1244 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1245 { return 0; | |
1246 } | |
1247 | |
1248 return( mb->max - mb->cur_memory_used); | |
1249 } | |
1250 | |
1251 /******************************************************************************* | |
1252 ** | |
1253 ** Function rvf_get_mb_unused_green_mem | |
1254 ** | |
1255 ** Description Called by an application to get the number of bytes available | |
1256 ** until the memory bank watermark. | |
1257 ** | |
1258 ** Parameters: memory bank id | |
1259 ** | |
1260 ** Returns UINT32: number of bytes available | |
1261 ** returns 0 if the memory bank has not been created. | |
1262 ** | |
1263 *******************************************************************************/ | |
1264 UINT32 rvf_get_mb_unused_green_mem(T_RVF_MB_ID mb_id) | |
1265 { T_RVF_MB * mb; | |
1266 mb = &rvf_banks[mb_id]; | |
1267 | |
1268 if ( mb->returned_red == TRUE) /* if a previous count buf or get buf has failed */ | |
1269 { return 0; | |
1270 } | |
1271 | |
1272 if( mb->cur_memory_used > mb->watermark) | |
1273 { return 0; | |
1274 } | |
1275 | |
1276 return( mb->watermark - mb->cur_memory_used); | |
1277 } | |
1278 | |
1279 /******************************************************************************* | |
1280 ** | |
1281 ** Function rvf_get_buf | |
1282 ** | |
1283 ** Description Called by an application to get a buffer from a memory bank | |
1284 ** | |
1285 ** Parameters: memory bank id, buffer size | |
1286 ** (return) buffer pointer to the allocated buffer or null if | |
1287 ** mb status is RVF_RED | |
1288 ** | |
1289 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1290 ** RVF_YELLOW if watermark limit has been reached, | |
1291 ** RVF_RED if max size has been reached (does not return a buffer) | |
1292 ** | |
1293 *******************************************************************************/ | |
1294 T_RVF_MB_STATUS rvf_get_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer) | |
1295 { T_RVF_MB * mb; | |
1296 | |
1297 /* checking for invalid memory bank IDs */ | |
1298 if (mb_id >= RVF_MAX_REAL_MB) | |
1299 { | |
1300 #ifdef RVM_DAR_SWE | |
1301 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1302 DAR_ASCII_FORMAT, | |
1303 RVM_USE_ID); | |
1304 #else | |
1305 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1306 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1307 NULL_PARAM, | |
1308 RV_TRACE_LEVEL_ERROR, | |
1309 RVM_USE_ID); | |
1310 #endif | |
1311 return RVF_RED; | |
1312 } | |
1313 mb = &rvf_banks[ mb_id ]; | |
1314 | |
1315 /* check memory usage */ | |
1316 if ( ( mb->cur_memory_used + buffer_size) > mb->max ) | |
1317 { /* over the limits, return RED and do not allocate a buffer */ | |
1318 mb->returned_red = TRUE; | |
1319 *p_buffer = NULL; | |
1320 return RVF_RED; | |
1321 } | |
1322 | |
1323 /* find a buffer of the requested size */ | |
1324 *p_buffer = _find_buf( buffer_size ); | |
1325 if ( *p_buffer == NULL ) /* error during allocation, not enough memory */ | |
1326 { //rvf_send_trace( "RVF: rvf_get_buf(): not enough available physical memory", 56, NULL_PARAM, RV_TRACE_LEVEL_ERROR, TRACE_RVF_BUFFER ); | |
1327 mb->returned_red = TRUE; | |
1328 return RVF_RED; | |
1329 } | |
1330 | |
1331 #if RVF_ENABLE_STATS | |
1332 required_size += buffer_size; | |
1333 obtained_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)); | |
1334 used_size += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1335 mem_in_use += rvf_get_buf_size((UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF)) + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1336 #endif | |
1337 | |
1338 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_disable(20); /* enter critical section */ | |
1339 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1340 /* set as unlinked */ | |
1341 RVF_SET_BUF_UNLINKED((T_RVF_INTERNAL_BUF*)(*p_buffer)); | |
1342 #endif | |
1343 | |
1344 /* increase memory use counter */ | |
1345 mb->cur_memory_used += rvf_get_buf_size( (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF) ); | |
1346 ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_id = mb_id; | |
1347 ( (T_RVF_INTERNAL_BUF *) (*p_buffer))->header.external.mb_expected = RVF_INVALID_MB_ID; | |
1348 | |
1349 *p_buffer = (UINT8*)(*p_buffer) + sizeof(T_RVF_INTERNAL_BUF); | |
1350 | |
1351 #if RVF_ENABLE_STATS | |
1352 if ( mb->cur_memory_used > mb->max_reached ) | |
1353 { mb->max_reached = mb->cur_memory_used; | |
1354 } | |
1355 mb->required_size += buffer_size; | |
1356 mb->num_buf++; | |
1357 #endif | |
1358 | |
1359 if(INC_Initialize_State==INC_END_INITIALIZE) rvf_enable(); /* exit critical section */ | |
1360 | |
1361 /* return the correct flag */ | |
1362 if ( mb->cur_memory_used > mb->watermark ) | |
1363 { return RVF_YELLOW; | |
1364 } | |
1365 else | |
1366 { return RVF_GREEN; | |
1367 } | |
1368 } | |
1369 | |
1370 /******************************************************************************* | |
1371 ** | |
1372 ** Function rvf_count_buf | |
1373 ** | |
1374 ** Description Called by an application to change the memory bank on which a buffer is counted | |
1375 ** | |
1376 ** Parameters: new memory bank id, | |
1377 ** pointer to the buffer. | |
1378 ** | |
1379 ** Returns T_RVF_MB_STATUS: RVF_GREEN if everything is ok, | |
1380 ** RVF_YELLOW if watermark limit has been reached, | |
1381 ** RVF_RED if max size has been reached | |
1382 ** | |
1383 *******************************************************************************/ | |
1384 T_RVF_MB_STATUS rvf_count_buf(T_RVF_MB_ID mb_id, T_RVF_BUFFER * p_buffer) | |
1385 { T_RVF_INTERNAL_BUF * buf; | |
1386 UINT32 buf_size; | |
1387 T_RVF_MB * new_mb; | |
1388 T_RVF_MB * old_mb; | |
1389 | |
1390 /* checking for invalid memory bank IDs */ | |
1391 if (mb_id >= RVF_MAX_REAL_MB) | |
1392 { | |
1393 #ifdef RVM_DAR_SWE | |
1394 dar_diagnose_generate_emergency (RVF_INVALID_MD_ID_ERRROR, | |
1395 DAR_ASCII_FORMAT, | |
1396 RVM_USE_ID); | |
1397 #else | |
1398 rvf_send_trace (RVF_INVALID_MD_ID_ERRROR, | |
1399 sizeof (RVF_INVALID_MD_ID_ERRROR) - 1, | |
1400 NULL_PARAM, | |
1401 RV_TRACE_LEVEL_ERROR, | |
1402 RVM_USE_ID); | |
1403 #endif | |
1404 return RVF_RED; | |
1405 } | |
1406 buf = (T_RVF_INTERNAL_BUF *) ( (UINT8 *) p_buffer - sizeof(T_RVF_INTERNAL_BUF) ); | |
1407 new_mb = &rvf_banks[mb_id]; | |
1408 old_mb = &rvf_banks[buf->header.external.mb_id]; | |
1409 | |
1410 /* get the size of the buffer and try to count it on the new mb */ | |
1411 buf_size = rvf_get_buf_size( p_buffer ); | |
1412 | |
1413 if ( ( new_mb->cur_memory_used + buf_size ) < new_mb->max ) | |
1414 { /* there is enough memory in the new mb */ | |
1415 | |
1416 if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID ) | |
1417 { /* remove the buffer from the list of waiting buffers in mb expected */ | |
1418 _remove_from_list( buf, &rvf_banks[buf->header.external.mb_expected] ); | |
1419 buf->header.external.mb_expected = RVF_INVALID_MB_ID; | |
1420 } | |
1421 | |
1422 rvf_disable(20); /* enter critical section */ | |
1423 | |
1424 /* decrease the memory used in the old mb */ | |
1425 old_mb->cur_memory_used -= buf_size; | |
1426 | |
1427 /* increase memory used in the new mb */ | |
1428 new_mb->cur_memory_used += buf_size; | |
1429 | |
1430 rvf_enable(); /* exit critical section */ | |
1431 | |
1432 /* call the callback function if state of the old mb switches to RVF_GREEN and there is no buffer waiting */ | |
1433 if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) ) | |
1434 { old_mb->returned_red = FALSE; | |
1435 old_mb->func( buf->header.external.mb_id); | |
1436 } | |
1437 else | |
1438 { /* count as many waiting buffers as possible on the old mb */ | |
1439 while( (old_mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( buf->header.external.mb_id, (UINT8 *) (waiting_buffers[old_mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) ); | |
1440 if ( (old_mb->cur_memory_used < old_mb->watermark) && (old_mb->first_buffer_index == RVF_INVALID_INDEX) && (old_mb->returned_red == TRUE) && ( old_mb->func != NULL) ) | |
1441 { old_mb->returned_red = FALSE; | |
1442 old_mb->func( buf->header.external.mb_id); | |
1443 } | |
1444 } | |
1445 /* change mb_id of the buffer */ | |
1446 buf->header.external.mb_id = mb_id; | |
1447 | |
1448 | |
1449 | |
1450 #if RVF_ENABLE_STATS | |
1451 if ( new_mb->cur_memory_used > new_mb->max_reached ) | |
1452 { new_mb->max_reached = new_mb->cur_memory_used; | |
1453 } | |
1454 #endif | |
1455 | |
1456 if ( new_mb->cur_memory_used > new_mb->watermark ) | |
1457 { return RVF_YELLOW; | |
1458 } | |
1459 else | |
1460 { return RVF_GREEN; | |
1461 } | |
1462 } | |
1463 else | |
1464 { /* there is not enough memory in the new mb_id */ | |
1465 if ( buf->header.external.mb_expected != RVF_INVALID_MB_ID) /* remove the buffer from old expected mb */ | |
1466 { _remove_from_list( buf, &rvf_banks[ buf->header.external.mb_expected] ); | |
1467 } | |
1468 /* enqueue the buffer in the list of waiting buffer */ | |
1469 buf->header.external.mb_expected = mb_id; | |
1470 _add_to_list( buf, new_mb ); | |
1471 new_mb->returned_red = TRUE; | |
1472 return RVF_RED; | |
1473 } | |
1474 } | |
1475 | |
1476 /******************************************************************************* | |
1477 ** | |
1478 ** Function rvf_free_buf | |
1479 ** | |
1480 ** Description Called by an application to free a buffer | |
1481 ** | |
1482 ** Parameters: buffer pointer | |
1483 ** | |
1484 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1485 ** | |
1486 *******************************************************************************/ | |
1487 T_RVF_RET rvf_free_buf( T_RVF_BUFFER * p_buffer) | |
1488 { T_RVF_INTERNAL_BUF * buf; | |
1489 T_RVF_MB * mb; | |
1490 T_RVF_MB_ID mb_id; | |
1491 UINT32 buf_size; | |
1492 | |
1493 | |
1494 buf = USER2MEM(p_buffer); | |
1495 | |
1496 mb_id = buf->header.external.mb_id; | |
1497 mb = &rvf_banks[mb_id]; | |
1498 buf_size = rvf_get_buf_size(p_buffer); | |
1499 | |
1500 /* do not need to change the mb id of the buffer, since it will be overwritten by p_prev */ | |
1501 | |
1502 /* free the buffer */ | |
1503 if ( !_release_buf(buf) ) | |
1504 { return RVF_MEMORY_ERR; | |
1505 } | |
1506 | |
1507 #if RVF_ENABLE_STATS | |
1508 mem_in_use -= buf_size + sizeof(T_RVF_INTERNAL_BUF) + RVF_CORRUPT_OVERHEAD; | |
1509 #endif | |
1510 | |
1511 rvf_disable(20); /* enter critical section */ | |
1512 | |
1513 /* decrease mb memory use */ | |
1514 mb->cur_memory_used -= buf_size; | |
1515 | |
1516 rvf_enable(); /* exit critical section */ | |
1517 | |
1518 | |
1519 /* call the callback function if state of the mb switches to RVF_GREEN and there is no buffer waiting */ | |
1520 if ( (mb->returned_red == TRUE) && (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && ( mb->func != NULL) ) | |
1521 { mb->returned_red = FALSE; | |
1522 mb->func( mb_id); | |
1523 } | |
1524 else | |
1525 { /* count as many waiting buffers as possible on the mb */ | |
1526 while( (mb->first_buffer_index != RVF_INVALID_INDEX) && (rvf_count_buf( mb_id, (UINT8 *) (waiting_buffers[mb->first_buffer_index]) + sizeof(T_RVF_INTERNAL_BUF)) != RVF_RED) ); | |
1527 if ( (mb->cur_memory_used < mb->watermark) && ( mb->first_buffer_index == RVF_INVALID_INDEX) && (mb->returned_red == TRUE) && ( mb->func != NULL) ) | |
1528 { mb->returned_red = FALSE; | |
1529 mb->func( mb_id); | |
1530 } | |
1531 } | |
1532 | |
1533 return RVF_OK; | |
1534 } | |
1535 | |
1536 | |
1537 /******************************************************************************* | |
1538 ** | |
1539 ** Function rvf_set_callback_func | |
1540 ** | |
1541 ** Description Called the first time an application wants to set the callback | |
1542 ** function associated to a memory bank. | |
1543 ** | |
1544 ** Parameters: memory bank id, pointer to the callback function. | |
1545 ** | |
1546 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1547 ** | |
1548 *******************************************************************************/ | |
1549 T_RVF_RET rvf_set_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func) | |
1550 { T_RVF_MB * mb; | |
1551 | |
1552 /* checking for invalid memory bank IDs */ | |
1553 if (mb_id >= RVF_MAX_REAL_MB) | |
1554 return RVF_INVALID_PARAMETER; | |
1555 mb = &rvf_banks[mb_id]; | |
1556 if ( (mb->max != 0) && (mb->func == NULL) ) /* if the mb has been created and the callback func has never been set */ | |
1557 { mb->func = func; | |
1558 return RVF_OK; | |
1559 } | |
1560 return RVF_INVALID_PARAMETER; | |
1561 } | |
1562 | |
1563 | |
1564 /******************************************************************************* | |
1565 ** | |
1566 ** Function rvf_change_callback_func | |
1567 ** | |
1568 ** Description Called by an application to change the callback | |
1569 ** function associated to a memory bank. | |
1570 ** It means the callback function has to be set before. | |
1571 ** | |
1572 ** Parameters: memory bank id, pointer to the callback function. | |
1573 ** | |
1574 ** Returns T_RVF_RET: T_RVF_OK if succesful, | |
1575 ** | |
1576 *******************************************************************************/ | |
1577 T_RVF_RET rvf_change_callback_func(T_RVF_MB_ID mb_id, MB_CALLBACK_FUNC func) | |
1578 { T_RVF_MB * mb; | |
1579 | |
1580 /* checking for invalid memory bank IDs */ | |
1581 if (mb_id >= RVF_MAX_REAL_MB) | |
1582 return RVF_INVALID_PARAMETER; | |
1583 mb = &rvf_banks[mb_id]; | |
1584 if ( (mb->max != 0) && (mb->func != NULL) ) /* if the mb has been created and the callback func has already been set */ | |
1585 { mb->func = func; | |
1586 return RVF_OK; | |
1587 } | |
1588 return RVF_INVALID_PARAMETER; | |
1589 } | |
1590 | |
1591 #ifdef _WINDOWS_ | |
1592 /******************************************************************************* | |
1593 ** | |
1594 ** Function _rvf_window_dump_mem | |
1595 ** | |
1596 ** Description Called by a C++ object to update the graphical display of | |
1597 ** memory | |
1598 ** | |
1599 ** Parameters: Opaque pointer to C++ object | |
1600 ** | |
1601 ** Returns void | |
1602 ** | |
1603 ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE | |
1604 ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY | |
1605 ** STATUS | |
1606 ** | |
1607 *******************************************************************************/ | |
1608 void _rvf_window_dump_mem(void *m) | |
1609 { | |
1610 | |
1611 | |
1612 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1613 char mb_info[100]; | |
1614 UINT16 num_mb, num_buf, index; | |
1615 UINT32 total_mem_size = 0; | |
1616 UINT32 total_max_used = 0; | |
1617 UINT32 total_cur_used = 0; | |
1618 T_RVF_MB * mb; | |
1619 | |
1620 | |
1621 for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ ) | |
1622 { | |
1623 /* trace the mb if it has been created*/ | |
1624 if ( rvf_name_id[num_mb].mb_params.size > 0 ) | |
1625 { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1626 num_buf = 0; | |
1627 index = mb->first_buffer_index; | |
1628 while ( index != RVF_INVALID_INDEX) | |
1629 { num_buf++; | |
1630 index = next_buffer[index]; | |
1631 } | |
1632 strcpy(mb_info,rvf_name_id[num_mb].mb_name); | |
1633 mb_info[10]='\0'; | |
1634 AddNewState(m,mb_info, | |
1635 mb->cur_memory_used,mb->max_reached,mb->watermark,mb->max); | |
1636 | |
1637 | |
1638 total_mem_size += mb->max; | |
1639 total_max_used += mb->max_reached; | |
1640 total_cur_used += mb->cur_memory_used; | |
1641 } | |
1642 } | |
1643 | |
1644 #endif /* RVF_ENABLE_STATS */ | |
1645 } | |
1646 | |
1647 #endif | |
1648 | |
1649 /******************************************************************************* | |
1650 ** | |
1651 ** Function rvf_dump_mem | |
1652 ** | |
1653 ** Description Called by an application to dump mb state and display statistics | |
1654 ** | |
1655 ** Parameters: None | |
1656 ** | |
1657 ** Returns void | |
1658 ** | |
1659 ** WARNING DON'T CHANGE THE SYNTAX OF DISPLAYED DATAS SINCE | |
1660 ** THEY ARE PARSED TO DISPLAY GRAPHICALLY THE MEMORY | |
1661 ** STATUS | |
1662 ** | |
1663 *******************************************************************************/ | |
1664 void rvf_dump_mem() | |
1665 { | |
1666 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1667 char mb_info[100]; | |
1668 UINT16 num_mb, num_buf, index; | |
1669 UINT32 total_mem_size = 0; | |
1670 UINT32 total_max_used = 0; | |
1671 UINT32 total_cur_used = 0; | |
1672 T_RVF_MB * mb; | |
1673 | |
1674 | |
1675 /* display memory required, obtained and ratio */ | |
1676 rvf_send_trace("MEM STAT: Total memory required", 31, required_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1677 rvf_send_trace("MEM STAT: Total memory obtained", 31, obtained_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1678 rvf_send_trace("MEM STAT: Total memory used ", 31, used_size, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1679 sprintf( mb_info,"MEM STAT: Mem usage ratio : %010f%%", ( (double)(required_size) / (double)(obtained_size) ) *100 ); | |
1680 rvf_send_trace(mb_info, 44, NULL_PARAM , RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1681 | |
1682 rvf_send_trace("*** START DUMPING MEMORY BANK ***", 33, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1683 /* for each mb, display its name, its id, its cur_size, its watermark, its limit, its max reached, the number of callback functions enqueued, | |
1684 (the requested size, the number of allocated buffer), the average buffer size for this mb */ | |
1685 rvf_send_trace("**MB_NAME* Id Used_mem Watermark Limit Peak Nb_buff Avg_buf_size", 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1686 | |
1687 for ( num_mb = 0; num_mb < RVF_MAX_TOTAL_MB; num_mb++ ) | |
1688 { | |
1689 /* trace the mb if it has been created*/ | |
1690 if ( rvf_name_id[num_mb].mb_params.size > 0 ) | |
1691 { mb = &rvf_banks[ rvf_name_id[num_mb].mb_id ]; | |
1692 num_buf = 0; | |
1693 index = mb->first_buffer_index; | |
1694 while ( index != RVF_INVALID_INDEX) | |
1695 { num_buf++; | |
1696 index = next_buffer[index]; | |
1697 } | |
1698 sprintf( mb_info, "%10.10s %2d %6d %6d %6d %6d %2d %6d", | |
1699 rvf_name_id[num_mb].mb_name, rvf_name_id[num_mb].mb_id, | |
1700 mb->cur_memory_used, mb->watermark, mb->max, mb->max_reached, num_buf, | |
1701 mb->num_buf == 0? 0:mb->required_size / mb->num_buf); | |
1702 | |
1703 rvf_send_trace( mb_info, 67, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1704 | |
1705 total_mem_size += mb->max; | |
1706 total_max_used += mb->max_reached; | |
1707 total_cur_used += mb->cur_memory_used; | |
1708 } | |
1709 } | |
1710 sprintf( mb_info, "TOTAL: ******** %6d********** %6d %6d", | |
1711 total_cur_used, total_mem_size, total_max_used ); | |
1712 | |
1713 rvf_send_trace( mb_info, 46, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
1714 | |
1715 #endif /* RVF_ENABLE_STATS */ | |
1716 } | |
1717 | |
1718 | |
1719 /******************************************************************************* | |
1720 ** | |
1721 ** Function rvf_get_available_mem | |
1722 ** | |
1723 ** Description Called to get the total size of the memory and the used size. | |
1724 ** | |
1725 ** Parameters: (return) UINT32 * total_size: contains the number of bytes in the memory. | |
1726 ** (return) UINT32 * used_size: contains the number of used bytes in the memory. | |
1727 ** | |
1728 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1729 ** | |
1730 *******************************************************************************/ | |
1731 T_RVF_RET rvf_get_available_mem( UINT32 * total_size, UINT32 * used_size ) | |
1732 { | |
1733 UINT16 count; | |
1734 *total_size = 0; | |
1735 *used_size = 0; | |
1736 | |
1737 /* check if there is enough available physical memory (static or dynamic): if Sum(mb size) <= Sum(pool size)*/ | |
1738 for ( count = 0; count < _rvf_get_number_of_pool(); count ++ ) /* sum the memory in pools */ | |
1739 { *total_size += _rvf_pools[count].pool_size; | |
1740 } | |
1741 /* sum the memory required by existing mb */ | |
1742 for ( count = 0; count < RVF_MAX_REAL_MB; count ++ ) | |
1743 { *used_size += rvf_banks[count].max; | |
1744 } | |
1745 | |
1746 return RVF_OK; | |
1747 } | |
1748 | |
1749 | |
1750 /******************************************************************************* | |
1751 ** | |
1752 ** Function rvf_get_mb_param | |
1753 ** | |
1754 ** Description return the parameters of a specific memory bank | |
1755 ** | |
1756 ** Parameters: T_RVF_MB_NAME: name of the memory bank | |
1757 ** (return) T_RVF_MB_PARAM*: parameter of the memory bank. | |
1758 ** | |
1759 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1760 ** | |
1761 *******************************************************************************/ | |
1762 T_RVF_RET rvf_get_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param) | |
1763 { UINT8 num_mb; | |
1764 | |
1765 /* find the mb name in the array */ | |
1766 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1767 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1768 { return RVF_INVALID_PARAMETER; | |
1769 } | |
1770 | |
1771 /* copy the parameters of the memory bank */ | |
1772 *param = rvf_name_id[num_mb].mb_params; | |
1773 | |
1774 return RVF_OK; | |
1775 } | |
1776 | |
1777 | |
1778 /******************************************************************************* | |
1779 ** | |
1780 ** Function rvf_set_mb_param | |
1781 ** | |
1782 ** Description change the parameters of a specific memory bank | |
1783 ** | |
1784 ** Parameters: T_RVF_MB_NAME: name of the memory bank | |
1785 ** T_RVF_MB_PARAM*: parameter of the memory bank. | |
1786 ** | |
1787 ** Returns T_RVF_RET: RVF_OK if successful, else a negative value. | |
1788 ** | |
1789 *******************************************************************************/ | |
1790 T_RVF_RET rvf_set_mb_param( T_RVF_MB_NAME mb_name, T_RVF_MB_PARAM * param) | |
1791 { UINT8 num_mb; | |
1792 T_RVF_MB_ID mb_id; | |
1793 T_RVF_MB * mb; | |
1794 | |
1795 /* find the mb name in the array */ | |
1796 for ( num_mb = 0; (num_mb < RVF_MAX_TOTAL_MB) && (!_str_cmp(mb_name, rvf_name_id[num_mb].mb_name) ); num_mb++); | |
1797 if ( num_mb == RVF_MAX_TOTAL_MB ) /* mb name not found */ | |
1798 { return RVF_INVALID_PARAMETER; | |
1799 } | |
1800 | |
1801 mb_id = rvf_name_id[num_mb].mb_id; | |
1802 mb = &rvf_banks[ mb_id ]; | |
1803 | |
1804 rvf_disable(20); /* enter critical section */ | |
1805 | |
1806 /* decrease the mb param by the old parameters */ | |
1807 mb->watermark -= rvf_name_id[num_mb].mb_params.watermark; | |
1808 mb->max -= rvf_name_id[num_mb].mb_params.size; | |
1809 | |
1810 /* save the mb parameters */ | |
1811 rvf_name_id[num_mb].mb_params.size = param->size; | |
1812 rvf_name_id[num_mb].mb_params.watermark = param->watermark; | |
1813 | |
1814 /* increase the mb param by the new parameters */ | |
1815 mb->watermark += param->watermark; | |
1816 mb->max += param->size; | |
1817 | |
1818 rvf_enable(); /* exit critical section */ | |
1819 | |
1820 /* dequeue callback functions if state switches to RVF_GREEN */ | |
1821 | |
1822 return RVF_OK; | |
1823 } | |
1824 | |
1825 | |
1826 | |
1827 | |
1828 /******************************************************************************* | |
1829 ** | |
1830 ** Function rvf_empty_mailboxes | |
1831 ** | |
1832 ** Description Called by rvf_exit_task to empty a task's mailboxes before | |
1833 ** killing it | |
1834 ** | |
1835 ** Parameters: task_id: task of wich the mailboxes have to be emptied | |
1836 ** | |
1837 ** Returns RV_OK | |
1838 ** | |
1839 *******************************************************************************/ | |
1840 T_RV_RET _rvf_empty_mailboxes (T_RVF_G_ADDR_ID task_id) | |
1841 { | |
1842 void * p_buf = NULL; | |
1843 T_RVF_INTERNAL_BUF * p_hdr; | |
1844 UINT8 mbox_id = 0; | |
1845 | |
1846 if (task_id >= MAX_RVF_TASKS) | |
1847 { | |
1848 rvf_send_trace( "RVF: rvf_empty_mbox(): invalid taskid: ", 39, task_id, RV_TRACE_LEVEL_ERROR, RVM_USE_ID ); | |
1849 return RVF_INVALID_PARAMETER; | |
1850 } | |
1851 | |
1852 for (mbox_id = 0; mbox_id< RVF_NUM_TASK_MBOX; mbox_id++) | |
1853 { /* while the chained list is not empty */ | |
1854 /*while ( OSTaskQFirst[task_id][mbox_id] ) | |
1855 { | |
1856 rvf_disable(9); | |
1857 | |
1858 p_hdr = OSTaskQFirst[task_id][mbox_id]; | |
1859 OSTaskQFirst[task_id][mbox_id] = p_hdr->p_next; | |
1860 */ | |
1861 while ( pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] ) | |
1862 { | |
1863 rvf_disable(9); | |
1864 | |
1865 p_hdr = pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id]; | |
1866 pRtAddrIdTable[task_id]->OSTaskQFirst[mbox_id] = p_hdr->p_next; | |
1867 | |
1868 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1869 /* set as unlinked */ | |
1870 RVF_SET_BUF_UNLINKED(p_hdr); | |
1871 #endif | |
1872 | |
1873 p_buf = (UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
1874 | |
1875 rvf_enable(); /* exit critical section */ | |
1876 | |
1877 rvf_free_buf(p_buf); | |
1878 } | |
1879 } | |
1880 | |
1881 | |
1882 return (RV_OK); | |
1883 } | |
1884 | |
1885 | |
1886 /******************************************************************************* | |
1887 ** | |
1888 ** Function rvf_scan_next | |
1889 ** | |
1890 ** Description return the next item in the queue if any. | |
1891 ** If the end of the queue is reached, returns NULL. | |
1892 ** If current item is NULL, returns the first item in the queue. | |
1893 ** | |
1894 ** Returns NULL if the end of the queue is reached, else a pointer to the buffer. | |
1895 ** | |
1896 *******************************************************************************/ | |
1897 T_RVF_BUFFER * rvf_scan_next (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf) | |
1898 { | |
1899 T_RVF_INTERNAL_BUF *p_hdr; | |
1900 | |
1901 if (!p_q->count) /* if the queue is empty */ | |
1902 return (NULL); | |
1903 | |
1904 if (p_buf == NULL) /* if current item == NULL, returns the first one */ | |
1905 { | |
1906 return (T_RVF_BUFFER*)p_q->p_first; | |
1907 } | |
1908 | |
1909 rvf_disable(12); /* enter critical section */ | |
1910 | |
1911 p_hdr = (T_RVF_INTERNAL_BUF *)((UINT8 *)p_buf - sizeof(T_RVF_INTERNAL_BUF)); | |
1912 p_hdr = p_hdr->p_next; | |
1913 if (p_hdr != NULL) | |
1914 { p_hdr = (T_RVF_INTERNAL_BUF*) ((UINT8 *)p_hdr + sizeof(T_RVF_INTERNAL_BUF)); | |
1915 } | |
1916 | |
1917 rvf_enable(); | |
1918 | |
1919 return (T_RVF_BUFFER*)p_hdr; | |
1920 } | |
1921 | |
1922 | |
1923 /******************************************************************************* | |
1924 ** | |
1925 ** Function rvf_remove_from_queue | |
1926 ** | |
1927 ** Description remove a specific item from a queue | |
1928 ** | |
1929 ** Returns RVF_OK if the item is removed, RVF_INTERNAL_ERR else. | |
1930 ** | |
1931 *******************************************************************************/ | |
1932 T_RVF_RET rvf_remove_from_queue (T_RVF_BUFFER_Q * p_q, T_RVF_BUFFER * p_buf) | |
1933 { | |
1934 T_RVF_INTERNAL_BUF *p_hdr; | |
1935 T_RVF_INTERNAL_BUF *p_target; | |
1936 | |
1937 | |
1938 if (!p_q->count) /* if the queue is empty */ | |
1939 return (RVF_INTERNAL_ERR); | |
1940 | |
1941 rvf_disable(12); /* enter critical section */ | |
1942 | |
1943 /* find the specific item in the queue */ | |
1944 p_target = USER2MEM((UINT8*)p_buf); | |
1945 p_hdr = USER2MEM( (UINT8 *)p_q->p_first); | |
1946 | |
1947 if( p_hdr == p_target ) | |
1948 { /* the specific item is the first one */ | |
1949 rvf_dequeue( p_q); | |
1950 rvf_enable(); | |
1951 return (RVF_OK); | |
1952 } | |
1953 | |
1954 while( (p_hdr->p_next != p_target) && (p_hdr->p_next != NULL) ) | |
1955 { p_hdr = p_hdr->p_next; | |
1956 } | |
1957 | |
1958 if( p_hdr->p_next == NULL) /* item not found */ | |
1959 { rvf_enable(); | |
1960 return (RVF_INTERNAL_ERR); | |
1961 } | |
1962 | |
1963 | |
1964 p_hdr->p_next = p_target->p_next; | |
1965 p_q->count--; | |
1966 | |
1967 /* if we removed the last buffer */ | |
1968 if (p_q->p_last == p_buf) | |
1969 { p_q->p_last = p_hdr + sizeof(T_RVF_INTERNAL_BUF); | |
1970 } | |
1971 | |
1972 p_target->p_next = NULL; | |
1973 | |
1974 #if RVF_ENABLE_BUF_LINKAGE_CHECK | |
1975 /* set as unlinked */ | |
1976 RVF_SET_BUF_UNLINKED(p_target); | |
1977 #endif | |
1978 | |
1979 rvf_enable(); /* exit critical section */ | |
1980 | |
1981 return (RVF_OK); | |
1982 } | |
1983 | |
1984 /******************************************************************************* | |
1985 ** | |
1986 ** Function rvf_dump_pool | |
1987 ** | |
1988 ** Description Called by an application to dump memory pool usage | |
1989 ** | |
1990 ** Parameters: None | |
1991 ** | |
1992 ** Returns void | |
1993 ** | |
1994 *******************************************************************************/ | |
1995 void rvf_dump_pool() | |
1996 { | |
1997 #if RVF_ENABLE_STATS /* conditional compilation if stats are enabled */ | |
1998 | |
1999 UINT16 num_pool; | |
2000 UINT32 total_mem = 0; | |
2001 | |
2002 /* display memory stats */ | |
2003 rvf_send_trace("*** START DUMPING MEMORY ***", 28, NULL_PARAM, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2004 | |
2005 /* display the total amount of memory available in the system */ | |
2006 /* and the total amount of memory currently in use */ | |
2007 for( num_pool = 0; num_pool < _rvf_get_number_of_pool(); num_pool++) | |
2008 { total_mem += _rvf_pools[num_pool].pool_size; | |
2009 } | |
2010 | |
2011 rvf_send_trace( "Total memory available ", 23, total_mem, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2012 rvf_send_trace( "Memory currently in use", 23, mem_in_use, RV_TRACE_LEVEL_DEBUG_HIGH, RVM_USE_ID); | |
2013 | |
2014 #endif /* RVF_ENABLE_STATS */ | |
2015 } | |
2016 | |
2017 static void rvf_free_protected_buf(void *buf) | |
2018 { | |
2019 rvf_free_buf(buf); | |
2020 } | |
2021 | |
2022 void rvf_get_protected_buf(T_RVF_MB_ID mb_id, UINT32 buffer_size, T_RVF_BUFFER** p_buffer) | |
2023 { | |
2024 T_RVF_MB_STATUS err; | |
2025 err=rvf_get_buf(mb_id,buffer_size,p_buffer); | |
2026 if (err==RVF_GREEN) | |
2027 { | |
2028 struct _protectedPtr_ *ptr; | |
2029 struct _exceptionContext_ *context; | |
2030 | |
2031 context=_currentExceptionContext_[rvf_get_taskid()]; | |
2032 err=rvf_get_buf(mb_id,sizeof(struct _protectedPtr_),(void*)&ptr); | |
2033 ptr->next=NULL; | |
2034 ptr->previous=NULL; | |
2035 ptr->ptr=*p_buffer; | |
2036 ptr->func=rvf_free_protected_buf; | |
2037 | |
2038 if (err==RVF_GREEN) | |
2039 { | |
2040 if (context->stack==NULL) | |
2041 { | |
2042 context->stack=ptr; | |
2043 } | |
2044 else | |
2045 { | |
2046 ptr->previous=context->stack; | |
2047 context->stack->next=ptr; | |
2048 context->stack=ptr; | |
2049 } | |
2050 } | |
2051 else | |
2052 { | |
2053 rvf_free_buf(*p_buffer); | |
2054 } | |
2055 } | |
2056 if (err!=RVF_GREEN) | |
2057 throw(E_not_enough_memory); | |
2058 } | |
2059 | |
2060 //TISHMMS Project | |
2061 /* add by xmzhou_trace_string to trace debug trace message */ | |
2062 void xmzhou_trace_string(char * string2trace) | |
2063 { | |
2064 rvf_send_trace(string2trace,strlen(string2trace),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2065 } | |
2066 | |
2067 void xmzhou_trace_string_value(char * string2trace,UINT32 value) | |
2068 { | |
2069 rvf_send_trace(string2trace,strlen(string2trace),value, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2070 } | |
2071 | |
2072 static void mychar2hex(char ch, char *str) | |
2073 { | |
2074 unsigned char h_nibble = (ch >> 4) & 0x0F; | |
2075 unsigned char l_nibble = ch & 0x0F; | |
2076 | |
2077 if (h_nibble < 10) | |
2078 str[0] = 48 + h_nibble; | |
2079 else | |
2080 str[0] = 55 + h_nibble; | |
2081 | |
2082 if (l_nibble < 10) | |
2083 str[1] = 48 + l_nibble; | |
2084 else | |
2085 str[1] = 55 + l_nibble; | |
2086 } | |
2087 | |
2088 void xmzhou_trace_n_bytes(char * buffer0, UINT32 len) | |
2089 { | |
2090 int i; | |
2091 int traced_len=0; | |
2092 char mybuffer[40]; | |
2093 char *tracebuffer; | |
2094 | |
2095 if(buffer0==NULL) return; | |
2096 | |
2097 xmzhou_trace_string_value("xmzhou dumping data length=",len); | |
2098 xmzhou_trace_string("-------"); | |
2099 | |
2100 | |
2101 while(traced_len<len){ | |
2102 | |
2103 if((len-traced_len)>=16){ | |
2104 tracebuffer=mybuffer; | |
2105 for (i = 0; i < 16; i++) { | |
2106 mychar2hex (buffer0[traced_len+i], tracebuffer); | |
2107 tracebuffer += 2; | |
2108 } | |
2109 traced_len+=16; | |
2110 *tracebuffer = '\0'; | |
2111 rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2112 rvf_delay(20); | |
2113 }else{ | |
2114 tracebuffer=mybuffer; | |
2115 for(i=0;i<(len-traced_len);i++) | |
2116 { | |
2117 mychar2hex (buffer0[traced_len+i], tracebuffer); | |
2118 tracebuffer += 2; | |
2119 } | |
2120 *tracebuffer = '\0'; | |
2121 rvf_send_trace(mybuffer,strlen(mybuffer),NULL_PARAM, RV_TRACE_LEVEL_DEBUG_LOW, RVM_USE_ID); | |
2122 rvf_delay(20); | |
2123 break; | |
2124 } | |
2125 | |
2126 } | |
2127 } |