1 /******************************************************************************
2 *
3 * Copyright (C) 2006-09, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov
11 *
12 * Contributors: Dmitri Ermakov
13 *
14 ******************************************************************************/
15
16 /*-----------------------------------------------------------------------------
17 * Id: memory L "Memory"
18 *
19 * Desc: Functions for memory management.
20 * Summary: Gentee has own memory manager. This overview describes the memory
21 management provided by Gentee. You can allocate and use memory with
22 these functions.
23 *
24 * List: *, malloc, mcmp, mcopy, mfree, mlen, mmove, mzero
25 *
26 -----------------------------------------------------------------------------*/
27
28 #include "../os/user/defines.h"
29 #include "memory.h"
30
31 memory _memory;
32 pubyte _lower;
33 pubyte _bin;
34 pubyte _hex;
35 pubyte _dec;
36 pubyte _name;
37 OS_CRL _crlmem; // Critical section for multi-thread calling
38
39 //uint memnum = 0;
40 //uint bufnum = 0;
41
42 /*--------------------------------------------------------------------------
43 *
44 * Locale functions
45 *
46 */
47
48 uint STDCALL _mem_heapalloc( uint id )
49 {
50 uint size;
51 pheap p_heap;
52
53 size = ( MEM_HEAPSIZE << ( id >> 5 ));
54
55 p_heap = _memory.heaps + id;
56
57 p_heap->ptr = os_alloc( size + MAX_BYTE * sizeof( uint ));
58 // p_heap->ptr = VirtualAlloc( NULL, size + MAX_BYTE * sizeof( uint ),
59 // MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
60 if ( !p_heap->ptr )
61 return FALSE;
62 p_heap->chain = p_heap->ptr;
63 p_heap->size = size;
64 p_heap->remain = size;
65 p_heap->free = 0;
66 // p_heap->count = 0;
67 // p_heap->alloc = 0;
68 mem_zeroui( p_heap->chain, MAX_BYTE );
69
70 // printf(".\n");
71 return TRUE;
72 }
73
74 //--------------------------------------------------------------------------
75
76 uint STDCALL _mem_heapfree( uint id )
77 {
78 pheap p_heap;
79
80 p_heap = _memory.heaps + id;
81 if ( p_heap->ptr )
82 // VirtualFree( p_heap->ptr, 0, MEM_RELEASE );
83 os_free( p_heap->ptr );
84 p_heap->ptr = 0;
85
86 return TRUE;
87 }
88
89 //--------------------------------------------------------------------------
90
91 uint STDCALL _mem_size2sid( uint size )
92 {
93 uint middle, right = 255;
94 uint left = 0;
95
96 while ( right > left )
97 {
98 middle = ( right + left ) >> 1;
99 if ( size > _memory.sid[ middle ] )
100 left = middle + 1;
101 else
102 right = middle;
103 }
104 return left;
105 }
106
107 /*-----------------------------------------------------------------------------
108 * Id: malloc F
109 *
110 * Summary: Allocate the memory. The function allocates the memory of the
111 specified size.
112 *
113 * Params: size - The size of memory space to be allocated.
114 *
115 * Return: The pointer to the allocated memory space or 0 in case of an error.
116 *
117 * Define: func uint malloc( uint size )
118 *
119 -----------------------------------------------------------------------------*/
120
121 pvoid STDCALL mem_alloc( uint size )
122 {
123 uint sid, ih;
124 pvoid result = 0;
125 pheap p_heap;
126
127 os_crlsection_enter( &_crlmem );
128 // memnum++;
129 if ( size > MEM_EDGE )
130 {
131 // ** result = ( pubyte )os_alloc( size + 8 ) + 2;
132 result = ( pubyte )os_alloc( size + 6 );
133 *(( pubyte )result + 5 ) = MAX_BYTE;
134 *( puint )result = size;
135 result = ( pubyte )result + 6;
136 goto end;
137 }
138 sid = _mem_size2sid( size );
139
140 ih = _memory.last;
141 size = _memory.sid[ sid ] + 2;
142
143 again:
144 p_heap = _memory.heaps + ih;
145 if ( !p_heap->ptr && !_mem_heapalloc( ih ))
146 {
147 result = 0;
148 goto end;
149 }
150 if ( p_heap->chain[ sid ] )
151 {
152 p_heap->free -= size;
153 result = ( pvoid )p_heap->chain[ sid ];
154 p_heap->chain[ sid ] = *( puint )result;
155 }
156 else
157 {
158 if ( size <= p_heap->remain )
159 {
160 result = ( pubyte )p_heap->ptr + MAX_BYTE * sizeof( uint ) +
161 p_heap->size - p_heap->remain;
162 *(( pubyte )result)++ = ( byte )ih;
163 *(( pubyte )result)++ = ( byte )sid;
164 p_heap->remain -= size;
165 }
166 else
167 {
168 if ( _memory.last )
169 {
170 _memory.last = 0;
171 ih = 0;
172 }
173 else
174 ih++;
175 goto again;
176 }
177 }
178 _memory.last = ih;
179 // p_heap->count++;
180 // p_heap->alloc += size;
181
182 end:
183 os_crlsection_leave( &_crlmem );
184
185 return result;
186 }
187
188 //--------------------------------------------------------------------------
189
190 pvoid STDCALL mem_allocz( uint size )
191 {
192 pvoid result = NULL;
193
194 result = mem_alloc( size );
195 if ( result )
196 mem_zero( result, size );
197
198 return result;
199 }
200
201 /*-----------------------------------------------------------------------------
202 * Id: mcopy F
203 *
204 * Summary: Copying memory. The function copies data from one memory space
205 into another.
206 *
207 * Params: dest - The pointer for the data being copied.
208 src - The pointer to the source of the data being copied.
209 len - The size of the data being copied.
210 *
211 * Return: The pointer to the copied data.
212 *
213 * Define: func uint mcopy( uint dest, uint src, uint len )
214 *
215 -----------------------------------------------------------------------------*/
216
217 pvoid STDCALL mem_copy( pvoid dest, pvoid src, uint len )
218 {
219 puint psrc = ( puint )src;
220 puint pdest = ( puint )dest;
221 uint ilen = len >> 2;
222
223 while ( ilen-- )
224 *pdest++ = *psrc++;
225
226 len &= 0x3;
227 while ( len-- )
228 *((pubyte)pdest)++ = *((pubyte)psrc)++;
229
230 return dest;
231 }
232
233 //--------------------------------------------------------------------------
234
235 uint STDCALL mem_deinit( void )
236 {
237 uint i;
238
239 mem_free( _lower );
240
241 for ( i = 0; i <= MAX_BYTE; i++ )
242 _mem_heapfree( i );
243
244 os_free( _memory.sid );
245 os_free( _memory.heaps );
246
247 os_crlsection_delete( &_crlmem );
248
249 return TRUE;
250 }
251
252 /*-----------------------------------------------------------------------------
253 * Id: mfree F
254 *
255 * Summary: Memory deallocation. The function deallocates memory.
256 *
257 * Params: ptr - The pointer to the memory space to be deallocated.
258 *
259 * Return: #lng/retf#
260 *
261 * Define: func uint mfree( uint ptr )
262 *
263 -----------------------------------------------------------------------------*/
264
265 uint STDCALL mem_free( pvoid ptr )
266 {
267 // pubyte p_id;
268 uint sid;
269 uint pid;
270 pheap p_heap;
271
272 if ( !ptr ) return TRUE;
273
274 // memnum--;
275 os_crlsection_enter( &_crlmem );
276
277 sid = *(( pubyte )ptr - 1 );
278 // p_id = ( pubyte )ptr - 2;
279 pid = *(( pubyte )ptr - 2 );
280
281 if ( sid == MAX_BYTE )
282 {
283 os_free( ( pubyte )ptr - 6 );
284 // ** os_free( ( pubyte )ptr - 8 );
285 goto end;
286 }
287 p_heap = _memory.heaps + pid;//*p_id;
288 *( puint )ptr = p_heap->chain[ sid ];
289 p_heap->chain[ sid ] = ( uint )ptr;
290
291 p_heap->free += _memory.sid[ sid ] + 2;
292 // p_heap->alloc -= _memory.sid[ sid ] + 2;
293 // p_heap->count--;
294 // ??? Почему то при последнем элементе иногда получается выход за границы
295 // if ( p_heap->free + p_heap->remain == p_heap->size )
296 // if ( !p_heap->count )
297 // _mem_heapfree( pid );
298
299 end:
300 os_crlsection_leave( &_crlmem );
301
302 return TRUE;
303 }
304
305 //--------------------------------------------------------------------------
306
307 uint STDCALL mem_getsize( pvoid ptr )
308 {
309 uint sid;
310
311 if (( sid = *((pubyte)ptr - 1 )) == MAX_BYTE )
312 return *( puint )((pubyte)ptr - 6 );
313 return _memory.sid[ sid ];
314 }
315
316 //--------------------------------------------------------------------------
317
318 uint STDCALL mem_init( void )
319 {
320 uint i, size, step = 8;
321
322 _memory.sid = os_alloc( ABC_COUNT /*( MAX_BYTE + 1 )*/ * sizeof( uint ));
323 _memory.sid[ 0 ] = step;
324 for ( i = 1; i < MAX_BYTE; i++ )
325 {
326 if ( !( i & 0xF ))
327 step <<= 1;
328 _memory.sid[ i ] = _memory.sid[ i - 1 ] + step;
329 }
330 _memory.sid[ MAX_BYTE ] = MAX_UINT;
331
332 _memory.heaps = os_alloc( size = ABC_COUNT * sizeof( heap ));
333 mem_zero( _memory.heaps, size );
334
335 os_crlsection_init( &_crlmem );
336 _memory.last = 0;
337
338 _lower = mem_alloc( ABC_COUNT * 5 );
339 _bin = _lower + ABC_COUNT;
340 _dec = _bin + ABC_COUNT;
341 _hex = _dec + ABC_COUNT;
342 _name = _hex + ABC_COUNT;
343
344 for ( i = 0; i < ABC_COUNT; i++ )
345 {
346 _lower[i] = ( ubyte )os_lower( ( pubyte )i );
347 _bin[i] = 0xFF;
348 if ( i >= '0' && i <= '9' )
349 _name[i] = 1;
350 else
351 if ( i >= 0x80 || ( i >= 'A' && i <= 'Z' ) || ( i >= 'a' && i <= 'z' ) ||
352 i == '_' )
353 _name[i] = 2;
354 else
355 _name[i] = 0;
356 }
357 _bin[ '0' ] = 0;
358 _bin[ '1' ] = 1;
359
360 for ( i = 0; i < ABC_COUNT; i++ )
361 if ( i > '1' && i <= '9' )
362 _dec[i] = (ubyte)( 1 + i - '1' );
363 else
364 _dec[i] = _bin[i];
365
366 for ( i = 0; i < ABC_COUNT; i++ )
367 if ( _lower[i] >= 'a' && _lower[i] <= 'f' )
368 _hex[i] = 10 + _lower[i] - 'a';
369 else
370 _hex[i] = _dec[i];
371
372 return TRUE;
373 }
374
375 /*-----------------------------------------------------------------------------
376 * Id: mlen F
377 *
378 * Summary: Size till zero. Determines the number of bytes till zero.
379 *
380 * Params: data - The pointer to a memory space.
381 *
382 * Return: The number of bytes till the zero character.
383 *
384 * Define: func uint mlen( uint data )
385 *
386 -----------------------------------------------------------------------------*/
387
388 uint STDCALL mem_len( pvoid data )
389 {
390 pubyte temp = ( pubyte )data;
391
392 while ( *temp++ );
393
394 return ( uint )( temp - ( pubyte )data - 1 );
395 }
396
397 //--------------------------------------------------------------------------
398
399 uint STDCALL mem_lensh( pvoid data )
400 {
401 pushort temp = ( pushort )data;
402
403 while ( *temp++ );
404
405 return ( uint )( temp - ( pushort )data - 1 );
406 }
407
408 /*-----------------------------------------------------------------------------
409 * Id: mmove F
410 *
411 * Summary: Move memory. The function moves the specified space. The initial and
412 final data may overlap.
413 *
414 * Params: dest - The pointer for the data being copied.
415 src - The pointer to the source of the data being copied.
416 len - The size of the data being copied.
417 *
418 * Define: func mmove( uint dest, uint src, uint len )
419 *
420 -----------------------------------------------------------------------------*/
421
422 void STDCALL mem_move( pvoid dest, pvoid src, uint len )
423 {
424 puint psrc;
425 puint pdest;
426 uint ilen;
427
428 if ( ( pubyte )dest <= ( pubyte )src ||
429 ( pubyte )dest >= ( pubyte )src + len )
430 mem_copy( dest, src, len );
431 else
432 {
433 ilen = len >> 2;
434 // области памяти пересекаются и надо копировать с конца
435 pdest = ( puint )( ( pubyte )dest + len - sizeof( uint ));
436 psrc = ( puint )(( pubyte )src + len - sizeof( uint ));
437 while ( ilen-- )
438 *pdest-- = *psrc--;
439
440 len &= 0x3;
441 while ( len-- )
442 *( ( pubyte )dest + len ) = *( ( pubyte )src + len );
443 }
444 }
445
446 /*-----------------------------------------------------------------------------
447 * Id: mzero F
448 *
449 * Summary: Filling memory with zeros. The functions zeroes the memory space.
450 *
451 * Params: dest - The pointer to a memory space.
452 len - The size of the data being zeroed.
453 *
454 * Return: The pointer to the zeroed data.
455 *
456 * Define: func uint mzero( uint dest, uint len )
457 *
458 -----------------------------------------------------------------------------*/
459
460 pvoid STDCALL mem_zero( pvoid dest, uint len )
461 {
462 puint p_dest = ( puint )dest;
463 uint ilen = len >> 2;
464
465 #ifdef LINUX
466 while ( ilen-- )
467 *p_dest++ = 0;
468 #else
469 __asm
470 {
471 mov edi, dest
472 mov ecx, ilen
473 mov eax, 0
474 rep stosd
475 }
476 p_dest += ilen;
477 #endif
478
479 len &= 0x3;
480 while ( len-- )
481 *((pubyte)p_dest)++ = 0;
482
483 return dest;
484 }
485
486 /*-----------------------------------------------------------------------------
487 ** Id: mcmp F
488 *
489 * Summary: Comparison memory. The function compares two memory spaces.
490 *
491 * Params: dest - The pointer to the first memory space.
492 src - The pointer to the second memory space.
493 len - The size being compared.
494 *
495 * Return: #tblparam[0|The spaces are equal.$#
496 <0|The first space is smaller.$#
497 >0|The second space is smaller.]
498 *
499 * Define: func int mcmp( uint dest, uint src, uint len )
500 *
501 -----------------------------------------------------------------------------*/
502
503 int STDCALL mem_cmp( pvoid dest, pvoid src, uint len )
504 {
505 puint dsrc = ( puint )src;
506 puint ddest = ( puint )dest;
507 uint ilen = len >> 2;
508 int i;
509
510 while ( ilen-- )
511 if ( *ddest++ != *dsrc++ )
512 {
513 ddest--;
514 dsrc--;
515 for ( i = 0; i < 4; i++ )
516 {
517 if ( *((pubyte)ddest) > *((pubyte)dsrc) )
518 return 1;
519 if ( *((pubyte)ddest)++ < *((pubyte)dsrc)++ )
520 return -1;
521 }
522 }
523
524 len &= 0x3;
525 while ( len-- )
526 {
527 if ( *((pubyte)ddest) > *((pubyte)dsrc) )
528 return 1;
529 if ( *((pubyte)ddest)++ < *((pubyte)dsrc)++ )
530 return -1;
531 }
532
533 return 0;
534 }
535
536 //--------------------------------------------------------------------------
537
538 int STDCALL mem_cmpign( pvoid dest, pvoid src, uint len )
539 {
540 pubyte psrc = ( pubyte )src;
541 pubyte pdest = ( pubyte )dest;
542
543 while ( len-- )
544 {
545 if ( _lower[ *pdest++ ] != _lower[ *psrc++ ] )
546 {
547 return *--pdest > *--psrc ? 1 : -1;
548 }
549 }
550 return 0;
551 }
552
553 //--------------------------------------------------------------------------
554
555 uint STDCALL mem_iseqzero( pvoid dest, pvoid src )
556 {
557 uint len = mem_len( dest );
558
559 return !mem_cmp( dest, src, len ) &&
560 (( pubyte )dest)[ len ] == (( pubyte )src)[ len ];
561 }
562
563 //--------------------------------------------------------------------------
564
565 void STDCALL mem_zeroui( puint dest, uint len )
566 {
567 #ifdef LINUX
568 while ( len-- )
569 *dest++ = 0;
570 #else
571 __asm
572 {
573 mov edi, dest
574 mov ecx, len
575 mov eax, 0
576 rep stosd
577 }
578 #endif
579 }
580
581 //--------------------------------------------------------------------------
582
583 void STDCALL mem_copyui( puint dest, puint src, uint len )
584 {
585 while ( len-- )
586 *dest++ = *src++;
587 }
588
589 //--------------------------------------------------------------------------
590
591 uint STDCALL mem_index( pubyte dest, uint number )
592 {
593 return ( uint )( dest + number );
594 }
595
596 //--------------------------------------------------------------------------
597
598 uint STDCALL mem_copyuntilzero( pubyte dest, pubyte src )
599 {
600 pubyte temp = dest;
601
602 while ( *src )
603 *temp++ = *src++;
604 *temp = 0;
605 return ( uint )( temp - dest + 1 );
606 }
607
608 //--------------------------------------------------------------------------
609
610 void STDCALL mem_swap( pubyte left, pubyte right, uint len )
611 {
612 /* register byte temp;
613
614 if ( left != right )
615 {
616 while ( len-- )
617 {
618 temp = *left;
619 *left++ = *right;
620 *right++ = temp;
621 }
622 }*/
623
624 register uint temp;
625 register uint dwlen = len >> 2;
626
627 if ( left != right )
628 {
629 while ( dwlen-- )
630 {
631 temp = *( puint )left;
632 *(( puint )left)++ = *( puint )right;
633 *(( puint )right)++ = temp;
634 }
635 len &= 0x3;
636 while ( len-- )
637 {
638 temp = *left;
639 *left++ = *right;
640 *right++ = ( ubyte )temp;
641 }
642 }
643 }
644 /*
645 uint memtest()
646 {
647 uint i;
648 pheap p_heap;
649
650 for ( i = 0; i <= MAX_BYTE; i++ )
651 {
652 p_heap = _memory.heaps + i;
653 if ( p_heap->ptr )
654 {
655 if ( p_heap->free + p_heap->remain + p_heap->alloc != p_heap->size )
656 return i+1;
657 }
658 }
659 return 0;
660 }*/
661 /*
662 #include "msg.h"
663
664 uint STDCALL memstat()
665 {
666 print("Memnum=%i buf=%i\n", memnum, bufnum );
667 return 0;
668 }*/