Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/ncsw/etc/ncsw_mem.c
48261 views
1
/******************************************************************************
2
3
� 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4
All rights reserved.
5
6
This is proprietary source code of Freescale Semiconductor Inc.,
7
and its use is subject to the NetComm Device Drivers EULA.
8
The copyright notice above does not evidence any actual or intended
9
publication of such source code.
10
11
ALTERNATIVELY, redistribution and use in source and binary forms, with
12
or without modification, are permitted provided that the following
13
conditions are met:
14
* Redistributions of source code must retain the above copyright
15
notice, this list of conditions and the following disclaimer.
16
* Redistributions in binary form must reproduce the above copyright
17
notice, this list of conditions and the following disclaimer in the
18
documentation and/or other materials provided with the distribution.
19
* Neither the name of Freescale Semiconductor nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
*
34
35
**************************************************************************/
36
#include "error_ext.h"
37
#include "part_ext.h"
38
#include "std_ext.h"
39
#include "string_ext.h"
40
#include "mem_ext.h"
41
#include "mem.h"
42
#include "xx_ext.h"
43
44
45
#if 0
46
#define PAD_ALIGNMENT(align, x) (((x)%(align)) ? ((align)-((x)%(align))) : 0)
47
48
#define ALIGN_BLOCK(p_Block, prefixSize, alignment) \
49
do { \
50
p_Block += (prefixSize); \
51
p_Block += PAD_ALIGNMENT((alignment), (uintptr_t)(p_Block)); \
52
} while (0)
53
54
#if defined(__GNUC__)
55
#define GET_CALLER_ADDR \
56
__asm__ ("mflr %0" : "=r" (callerAddr))
57
#elif defined(__MWERKS__)
58
/* NOTE: This implementation is only valid for CodeWarrior for PowerPC */
59
#define GET_CALLER_ADDR \
60
__asm__("add %0, 0, %0" : : "r" (callerAddr))
61
#endif /* defined(__GNUC__) */
62
63
64
/*****************************************************************************/
65
static __inline__ void * MemGet(t_MemorySegment *p_Mem)
66
{
67
uint8_t *p_Block;
68
69
/* check if there is an available block */
70
if (p_Mem->current == p_Mem->num)
71
{
72
p_Mem->getFailures++;
73
return NULL;
74
}
75
76
/* get the block */
77
p_Block = p_Mem->p_BlocksStack[p_Mem->current];
78
#ifdef DEBUG
79
p_Mem->p_BlocksStack[p_Mem->current] = NULL;
80
#endif /* DEBUG */
81
/* advance current index */
82
p_Mem->current++;
83
84
return (void *)p_Block;
85
}
86
87
/*****************************************************************************/
88
static __inline__ t_Error MemPut(t_MemorySegment *p_Mem, void *p_Block)
89
{
90
/* check if blocks stack is full */
91
if (p_Mem->current > 0)
92
{
93
/* decrease current index */
94
p_Mem->current--;
95
/* put the block */
96
p_Mem->p_BlocksStack[p_Mem->current] = (uint8_t *)p_Block;
97
return E_OK;
98
}
99
100
RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
101
}
102
103
104
#ifdef DEBUG_MEM_LEAKS
105
106
/*****************************************************************************/
107
static t_Error InitMemDebugDatabase(t_MemorySegment *p_Mem)
108
{
109
p_Mem->p_MemDbg = (void *)XX_Malloc(sizeof(t_MemDbg) * p_Mem->num);
110
if (!p_Mem->p_MemDbg)
111
{
112
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory debug object"));
113
}
114
115
memset(p_Mem->p_MemDbg, ILLEGAL_BASE, sizeof(t_MemDbg) * p_Mem->num);
116
117
return E_OK;
118
}
119
120
121
/*****************************************************************************/
122
static t_Error DebugMemGet(t_Handle h_Mem, void *p_Block, uintptr_t ownerAddress)
123
{
124
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
125
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
126
uint32_t blockIndex;
127
128
ASSERT_COND(ownerAddress != ILLEGAL_BASE);
129
130
/* Find block num */
131
if (p_Mem->consecutiveMem)
132
{
133
blockIndex =
134
(((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
135
}
136
else
137
{
138
blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
139
}
140
141
ASSERT_COND(blockIndex < p_Mem->num);
142
ASSERT_COND(p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE);
143
144
p_MemDbg[blockIndex].ownerAddress = ownerAddress;
145
146
return E_OK;
147
}
148
149
/*****************************************************************************/
150
static t_Error DebugMemPut(t_Handle h_Mem, void *p_Block)
151
{
152
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
153
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
154
uint32_t blockIndex;
155
uint8_t *p_Temp;
156
157
/* Find block num */
158
if (p_Mem->consecutiveMem)
159
{
160
blockIndex =
161
(((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
162
163
if (blockIndex >= p_Mem->num)
164
{
165
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
166
("Freed address (0x%08x) does not belong to this pool", p_Block));
167
}
168
}
169
else
170
{
171
blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
172
173
if (blockIndex >= p_Mem->num)
174
{
175
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
176
("Freed address (0x%08x) does not belong to this pool", p_Block));
177
}
178
179
/* Verify that the block matches the corresponding base */
180
p_Temp = p_Mem->p_Bases[blockIndex];
181
182
ALIGN_BLOCK(p_Temp, p_Mem->prefixSize, p_Mem->alignment);
183
184
if (p_Temp == p_Mem->p_Bases[blockIndex])
185
p_Temp += p_Mem->alignment;
186
187
if (p_Temp != p_Block)
188
{
189
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
190
("Freed address (0x%08x) does not belong to this pool", p_Block));
191
}
192
}
193
194
if (p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE)
195
{
196
RETURN_ERROR(MAJOR, E_ALREADY_FREE,
197
("Attempt to free unallocated address (0x%08x)", p_Block));
198
}
199
200
p_MemDbg[blockIndex].ownerAddress = (uintptr_t)ILLEGAL_BASE;
201
202
return E_OK;
203
}
204
205
#endif /* DEBUG_MEM_LEAKS */
206
207
208
/*****************************************************************************/
209
uint32_t MEM_ComputePartitionSize(uint32_t num,
210
uint16_t dataSize,
211
uint16_t prefixSize,
212
uint16_t postfixSize,
213
uint16_t alignment)
214
{
215
uint32_t blockSize = 0, pad1 = 0, pad2 = 0;
216
217
/* Make sure that the alignment is at least 4 */
218
if (alignment < 4)
219
{
220
alignment = 4;
221
}
222
223
pad1 = (uint32_t)PAD_ALIGNMENT(4, prefixSize);
224
/* Block size not including 2nd padding */
225
blockSize = pad1 + prefixSize + dataSize + postfixSize;
226
pad2 = PAD_ALIGNMENT(alignment, blockSize);
227
/* Block size including 2nd padding */
228
blockSize += pad2;
229
230
return ((num * blockSize) + alignment);
231
}
232
233
/*****************************************************************************/
234
t_Error MEM_Init(char name[],
235
t_Handle *p_Handle,
236
uint32_t num,
237
uint16_t dataSize,
238
uint16_t prefixSize,
239
uint16_t postfixSize,
240
uint16_t alignment)
241
{
242
uint8_t *p_Memory;
243
uint32_t allocSize;
244
t_Error errCode;
245
246
allocSize = MEM_ComputePartitionSize(num,
247
dataSize,
248
prefixSize,
249
postfixSize,
250
alignment);
251
252
p_Memory = (uint8_t *)XX_Malloc(allocSize);
253
if (!p_Memory)
254
{
255
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment"));
256
}
257
258
errCode = MEM_InitByAddress(name,
259
p_Handle,
260
num,
261
dataSize,
262
prefixSize,
263
postfixSize,
264
alignment,
265
p_Memory);
266
if (errCode != E_OK)
267
{
268
RETURN_ERROR(MAJOR, errCode, NO_MSG);
269
}
270
271
((t_MemorySegment *)(*p_Handle))->allocOwner = e_MEM_ALLOC_OWNER_LOCAL;
272
273
return E_OK;
274
}
275
276
277
/*****************************************************************************/
278
t_Error MEM_InitByAddress(char name[],
279
t_Handle *p_Handle,
280
uint32_t num,
281
uint16_t dataSize,
282
uint16_t prefixSize,
283
uint16_t postfixSize,
284
uint16_t alignment,
285
uint8_t *p_Memory)
286
{
287
t_MemorySegment *p_Mem;
288
uint32_t i, blockSize;
289
uint16_t alignPad, endPad;
290
uint8_t *p_Blocks;
291
292
/* prepare in case of error */
293
*p_Handle = NULL;
294
295
if (!p_Memory)
296
{
297
RETURN_ERROR(MAJOR, E_NULL_POINTER, ("Memory blocks"));
298
}
299
300
p_Blocks = p_Memory;
301
302
/* make sure that the alignment is at least 4 and power of 2 */
303
if (alignment < 4)
304
{
305
alignment = 4;
306
}
307
else if (!POWER_OF_2(alignment))
308
{
309
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
310
}
311
312
/* first allocate the segment descriptor */
313
p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
314
if (!p_Mem)
315
{
316
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
317
}
318
319
/* allocate the blocks stack */
320
p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
321
if (!p_Mem->p_BlocksStack)
322
{
323
XX_Free(p_Mem);
324
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
325
}
326
327
/* allocate the blocks bases array */
328
p_Mem->p_Bases = (uint8_t **)XX_Malloc(sizeof(uint8_t*));
329
if (!p_Mem->p_Bases)
330
{
331
MEM_Free(p_Mem);
332
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
333
}
334
memset(p_Mem->p_Bases, 0, sizeof(uint8_t*));
335
336
/* store info about this segment */
337
p_Mem->num = num;
338
p_Mem->current = 0;
339
p_Mem->dataSize = dataSize;
340
p_Mem->p_Bases[0] = p_Blocks;
341
p_Mem->getFailures = 0;
342
p_Mem->allocOwner = e_MEM_ALLOC_OWNER_EXTERNAL;
343
p_Mem->consecutiveMem = TRUE;
344
p_Mem->prefixSize = prefixSize;
345
p_Mem->postfixSize = postfixSize;
346
p_Mem->alignment = alignment;
347
/* store name */
348
strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1);
349
350
p_Mem->h_Spinlock = XX_InitSpinlock();
351
if (!p_Mem->h_Spinlock)
352
{
353
MEM_Free(p_Mem);
354
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
355
}
356
357
alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
358
/* Make sure the entire size is a multiple of alignment */
359
endPad = (uint16_t)PAD_ALIGNMENT(alignment, (alignPad + prefixSize + dataSize + postfixSize));
360
361
/* The following manipulation places the data of block[0] in an aligned address,
362
since block size is aligned the following block datas will all be aligned */
363
ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
364
365
blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
366
367
/* initialize the blocks */
368
for (i=0; i < num; i++)
369
{
370
p_Mem->p_BlocksStack[i] = p_Blocks;
371
p_Blocks += blockSize;
372
}
373
374
/* return handle to caller */
375
*p_Handle = (t_Handle)p_Mem;
376
377
#ifdef DEBUG_MEM_LEAKS
378
{
379
t_Error errCode = InitMemDebugDatabase(p_Mem);
380
381
if (errCode != E_OK)
382
RETURN_ERROR(MAJOR, errCode, NO_MSG);
383
384
p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
385
p_Mem->blockSize = blockSize;
386
}
387
#endif /* DEBUG_MEM_LEAKS */
388
389
return E_OK;
390
}
391
392
393
/*****************************************************************************/
394
t_Error MEM_InitSmart(char name[],
395
t_Handle *p_Handle,
396
uint32_t num,
397
uint16_t dataSize,
398
uint16_t prefixSize,
399
uint16_t postfixSize,
400
uint16_t alignment,
401
uint8_t memPartitionId,
402
bool consecutiveMem)
403
{
404
t_MemorySegment *p_Mem;
405
uint32_t i, blockSize;
406
uint16_t alignPad, endPad;
407
408
/* prepare in case of error */
409
*p_Handle = NULL;
410
411
/* make sure that size is always a multiple of 4 */
412
if (dataSize & 3)
413
{
414
dataSize &= ~3;
415
dataSize += 4;
416
}
417
418
/* make sure that the alignment is at least 4 and power of 2 */
419
if (alignment < 4)
420
{
421
alignment = 4;
422
}
423
else if (!POWER_OF_2(alignment))
424
{
425
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
426
}
427
428
/* first allocate the segment descriptor */
429
p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
430
if (!p_Mem)
431
{
432
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
433
}
434
435
/* allocate the blocks stack */
436
p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
437
if (!p_Mem->p_BlocksStack)
438
{
439
MEM_Free(p_Mem);
440
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
441
}
442
443
/* allocate the blocks bases array */
444
p_Mem->p_Bases = (uint8_t **)XX_Malloc((consecutiveMem ? 1 : num) * sizeof(uint8_t*));
445
if (!p_Mem->p_Bases)
446
{
447
MEM_Free(p_Mem);
448
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
449
}
450
memset(p_Mem->p_Bases, 0, (consecutiveMem ? 1 : num) * sizeof(uint8_t*));
451
452
/* store info about this segment */
453
p_Mem->num = num;
454
p_Mem->current = 0;
455
p_Mem->dataSize = dataSize;
456
p_Mem->getFailures = 0;
457
p_Mem->allocOwner = e_MEM_ALLOC_OWNER_LOCAL_SMART;
458
p_Mem->consecutiveMem = consecutiveMem;
459
p_Mem->prefixSize = prefixSize;
460
p_Mem->postfixSize = postfixSize;
461
p_Mem->alignment = alignment;
462
463
p_Mem->h_Spinlock = XX_InitSpinlock();
464
if (!p_Mem->h_Spinlock)
465
{
466
MEM_Free(p_Mem);
467
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
468
}
469
470
alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
471
/* Make sure the entire size is a multiple of alignment */
472
endPad = (uint16_t)PAD_ALIGNMENT(alignment, alignPad + prefixSize + dataSize + postfixSize);
473
474
/* Calculate blockSize */
475
blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
476
477
/* Now allocate the blocks */
478
if (p_Mem->consecutiveMem)
479
{
480
/* |alignment - 1| bytes at most will be discarded in the beginning of the
481
received segment for alignment reasons, therefore the allocation is of:
482
(alignment + (num * block size)). */
483
uint8_t *p_Blocks = (uint8_t *)
484
XX_MallocSmart((uint32_t)((num * blockSize) + alignment), memPartitionId, 1);
485
if (!p_Blocks)
486
{
487
MEM_Free(p_Mem);
488
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
489
}
490
491
/* Store the memory segment address */
492
p_Mem->p_Bases[0] = p_Blocks;
493
494
/* The following manipulation places the data of block[0] in an aligned address,
495
since block size is aligned the following block datas will all be aligned.*/
496
ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
497
498
/* initialize the blocks */
499
for (i = 0; i < num; i++)
500
{
501
p_Mem->p_BlocksStack[i] = p_Blocks;
502
p_Blocks += blockSize;
503
}
504
505
#ifdef DEBUG_MEM_LEAKS
506
p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
507
p_Mem->blockSize = blockSize;
508
#endif /* DEBUG_MEM_LEAKS */
509
}
510
else
511
{
512
/* |alignment - 1| bytes at most will be discarded in the beginning of the
513
received segment for alignment reasons, therefore the allocation is of:
514
(alignment + block size). */
515
for (i = 0; i < num; i++)
516
{
517
uint8_t *p_Block = (uint8_t *)
518
XX_MallocSmart((uint32_t)(blockSize + alignment), memPartitionId, 1);
519
if (!p_Block)
520
{
521
MEM_Free(p_Mem);
522
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
523
}
524
525
/* Store the memory segment address */
526
p_Mem->p_Bases[i] = p_Block;
527
528
/* The following places the data of each block in an aligned address */
529
ALIGN_BLOCK(p_Block, prefixSize, alignment);
530
531
#ifdef DEBUG_MEM_LEAKS
532
/* Need 4 bytes before the meaningful bytes to store the block index.
533
We know we have them because alignment is at least 4 bytes. */
534
if (p_Block == p_Mem->p_Bases[i])
535
p_Block += alignment;
536
537
*(uint32_t *)(p_Block - 4) = i;
538
#endif /* DEBUG_MEM_LEAKS */
539
540
p_Mem->p_BlocksStack[i] = p_Block;
541
}
542
}
543
544
/* store name */
545
strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1);
546
547
/* return handle to caller */
548
*p_Handle = (t_Handle)p_Mem;
549
550
#ifdef DEBUG_MEM_LEAKS
551
{
552
t_Error errCode = InitMemDebugDatabase(p_Mem);
553
554
if (errCode != E_OK)
555
RETURN_ERROR(MAJOR, errCode, NO_MSG);
556
}
557
#endif /* DEBUG_MEM_LEAKS */
558
559
return E_OK;
560
}
561
562
563
/*****************************************************************************/
564
void MEM_Free(t_Handle h_Mem)
565
{
566
t_MemorySegment *p_Mem = (t_MemorySegment*)h_Mem;
567
uint32_t num, i;
568
569
/* Check MEM leaks */
570
MEM_CheckLeaks(h_Mem);
571
572
if (p_Mem)
573
{
574
num = p_Mem->consecutiveMem ? 1 : p_Mem->num;
575
576
if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL_SMART)
577
{
578
for (i=0; i < num; i++)
579
{
580
if (p_Mem->p_Bases[i])
581
{
582
XX_FreeSmart(p_Mem->p_Bases[i]);
583
}
584
}
585
}
586
else if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL)
587
{
588
for (i=0; i < num; i++)
589
{
590
if (p_Mem->p_Bases[i])
591
{
592
XX_Free(p_Mem->p_Bases[i]);
593
}
594
}
595
}
596
597
if (p_Mem->h_Spinlock)
598
XX_FreeSpinlock(p_Mem->h_Spinlock);
599
600
if (p_Mem->p_Bases)
601
XX_Free(p_Mem->p_Bases);
602
603
if (p_Mem->p_BlocksStack)
604
XX_Free(p_Mem->p_BlocksStack);
605
606
#ifdef DEBUG_MEM_LEAKS
607
if (p_Mem->p_MemDbg)
608
XX_Free(p_Mem->p_MemDbg);
609
#endif /* DEBUG_MEM_LEAKS */
610
611
XX_Free(p_Mem);
612
}
613
}
614
615
616
/*****************************************************************************/
617
void * MEM_Get(t_Handle h_Mem)
618
{
619
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
620
uint8_t *p_Block;
621
uint32_t intFlags;
622
#ifdef DEBUG_MEM_LEAKS
623
uintptr_t callerAddr = 0;
624
625
GET_CALLER_ADDR;
626
#endif /* DEBUG_MEM_LEAKS */
627
628
ASSERT_COND(h_Mem);
629
630
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
631
/* check if there is an available block */
632
if ((p_Block = (uint8_t *)MemGet(p_Mem)) == NULL)
633
{
634
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
635
return NULL;
636
}
637
638
#ifdef DEBUG_MEM_LEAKS
639
DebugMemGet(p_Mem, p_Block, callerAddr);
640
#endif /* DEBUG_MEM_LEAKS */
641
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
642
643
return (void *)p_Block;
644
}
645
646
647
/*****************************************************************************/
648
uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[])
649
{
650
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
651
uint32_t availableBlocks;
652
register uint32_t i;
653
uint32_t intFlags;
654
#ifdef DEBUG_MEM_LEAKS
655
uintptr_t callerAddr = 0;
656
657
GET_CALLER_ADDR;
658
#endif /* DEBUG_MEM_LEAKS */
659
660
ASSERT_COND(h_Mem);
661
662
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
663
/* check how many blocks are available */
664
availableBlocks = (uint32_t)(p_Mem->num - p_Mem->current);
665
if (num > availableBlocks)
666
{
667
num = availableBlocks;
668
}
669
670
for (i=0; i < num; i++)
671
{
672
/* get pointer to block */
673
if ((array[i] = MemGet(p_Mem)) == NULL)
674
{
675
break;
676
}
677
678
#ifdef DEBUG_MEM_LEAKS
679
DebugMemGet(p_Mem, array[i], callerAddr);
680
#endif /* DEBUG_MEM_LEAKS */
681
}
682
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
683
684
return (uint16_t)i;
685
}
686
687
688
/*****************************************************************************/
689
t_Error MEM_Put(t_Handle h_Mem, void *p_Block)
690
{
691
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
692
t_Error rc;
693
uint32_t intFlags;
694
695
ASSERT_COND(h_Mem);
696
697
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
698
/* check if blocks stack is full */
699
if ((rc = MemPut(p_Mem, p_Block)) != E_OK)
700
{
701
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
702
RETURN_ERROR(MAJOR, rc, NO_MSG);
703
}
704
705
#ifdef DEBUG_MEM_LEAKS
706
DebugMemPut(p_Mem, p_Block);
707
#endif /* DEBUG_MEM_LEAKS */
708
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
709
710
return E_OK;
711
}
712
713
714
#ifdef DEBUG_MEM_LEAKS
715
716
/*****************************************************************************/
717
void MEM_CheckLeaks(t_Handle h_Mem)
718
{
719
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
720
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
721
uint8_t *p_Block;
722
int i;
723
724
ASSERT_COND(h_Mem);
725
726
if (p_Mem->consecutiveMem)
727
{
728
for (i=0; i < p_Mem->num; i++)
729
{
730
if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
731
{
732
/* Find the block address */
733
p_Block = ((p_Mem->p_Bases[0] + p_Mem->blockOffset) +
734
(i * p_Mem->blockSize));
735
736
XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
737
p_Block, p_MemDbg[i].ownerAddress);
738
}
739
}
740
}
741
else
742
{
743
for (i=0; i < p_Mem->num; i++)
744
{
745
if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
746
{
747
/* Find the block address */
748
p_Block = p_Mem->p_Bases[i];
749
750
ALIGN_BLOCK(p_Block, p_Mem->prefixSize, p_Mem->alignment);
751
752
if (p_Block == p_Mem->p_Bases[i])
753
p_Block += p_Mem->alignment;
754
755
XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
756
p_Block, p_MemDbg[i].ownerAddress);
757
}
758
}
759
}
760
}
761
762
#endif /* DEBUG_MEM_LEAKS */
763
764
765
#endif
766
767