memory_pools.c 24.4 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
17
18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
20
21
22
23
24
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27
28
29

 *******************************************************************************/

winckel's avatar
winckel committed
30
31
32
33
#ifdef RTAI
# include <rtai_shm.h>
#endif

34
35
#include "assertions.h"
#include "memory_pools.h"
36
37
38
#if defined(OAI_EMU) || defined(RTAI)
# include "vcd_signal_dumper.h"
#endif
39

40
41
42
43
44
45
46
47
48
49
50
/*------------------------------------------------------------------------------*/
const static int mp_debug = 0;

#ifdef RTAI
# define MP_DEBUG(x, args...) do { if (mp_debug) rt_printk("[MP][D]"x, ##args); } \
    while(0)
#else
# define MP_DEBUG(x, args...) do { if (mp_debug) fprintf(stdout, "[MP][D]"x, ##args); fflush (stdout); } \
    while(0)
#endif

51
52
53
54
55
#if defined(OAI_EMU) || defined(RTAI)
uint64_t vcd_mp_alloc;
uint64_t vcd_mp_free;
#endif

56
57
58
/*------------------------------------------------------------------------------*/
#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))

winckel's avatar
winckel committed
59
60
#define MEMORY_POOL_ITEM_INFO_NUMBER    2

61
/*------------------------------------------------------------------------------*/
62
63
typedef int32_t     items_group_position_t;
typedef int32_t     items_group_index_t;
64

winckel's avatar
winckel committed
65
typedef union items_group_positions_u {
66
67
68
69
70
  uint64_t                    all;
  struct {
    items_group_position_t  put;
    items_group_position_t  get;
  } ind;
winckel's avatar
winckel committed
71
72
} items_group_positions_t;

73
typedef struct items_group_s {
74
75
76
77
  items_group_position_t              number_plus_one;
  volatile uint32_t                   minimum;
  volatile items_group_positions_t    positions;
  volatile items_group_index_t       *indexes;
78
} items_group_t;
79

80
81
82
/*------------------------------------------------------------------------------*/
static const items_group_position_t ITEMS_GROUP_POSITION_INVALID    = -1;
static const items_group_index_t    ITEMS_GROUP_INDEX_INVALID       = -1;
83

84
85
86
87
88
89
90
91
92
93
94
/*------------------------------------------------------------------------------*/
typedef uint32_t    pool_item_start_mark_t;
typedef uint32_t    pool_item_end_mark_t;

typedef uint32_t    memory_pool_data_t;

typedef uint32_t    pool_start_mark_t;

typedef uint32_t    pools_start_mark_t;

typedef uint8_t     pool_id_t;
95
typedef uint8_t     item_status_t;
96
97

typedef struct memory_pool_item_start_s {
98
  pool_item_start_mark_t      start_mark;
99

100
101
102
  pool_id_t                   pool_id;
  item_status_t               item_status;
  uint16_t                    info[MEMORY_POOL_ITEM_INFO_NUMBER];
103
104
105
} memory_pool_item_start_t;

typedef struct memory_pool_item_end_s {
106
  pool_item_end_mark_t        end_mark;
107
108
109
} memory_pool_item_end_t;

typedef struct memory_pool_item_s {
110
111
112
  memory_pool_item_start_t    start;
  memory_pool_data_t          data[0];
  memory_pool_item_end_t      end;
113
114
115
} memory_pool_item_t;

typedef struct memory_pool_s {
116
  pool_start_mark_t           start_mark;
117

118
119
120
121
122
  pool_id_t                   pool_id;
  uint32_t                    item_data_number;
  uint32_t                    pool_item_size;
  items_group_t               items_group_free;
  memory_pool_item_t         *items;
123
124
} memory_pool_t;

125

126
typedef struct memory_pools_s {
127
  pools_start_mark_t          start_mark;
128

129
130
131
  uint32_t                    pools_number;
  uint32_t                    pools_defined;
  memory_pool_t              *pools;
132
133
134
135
} memory_pools_t;

/*------------------------------------------------------------------------------*/
static const uint32_t               MAX_POOLS_NUMBER =      20;
136
static const uint32_t               MAX_POOL_ITEMS_NUMBER = 200 * 1000;
137
138
139
140
141
static const uint32_t               MAX_POOL_ITEM_SIZE =    100 * 1000;

static const pool_item_start_mark_t POOL_ITEM_START_MARK =  CHARS_TO_UINT32 ('P', 'I', 's', 't');
static const pool_item_end_mark_t   POOL_ITEM_END_MARK =    CHARS_TO_UINT32 ('p', 'i', 'E', 'N');

142
143
144
static const item_status_t          ITEM_STATUS_FREE =      'F';
static const item_status_t          ITEM_STATUS_ALLOCATED = 'a';

145
146
147
148
149
static const pool_start_mark_t      POOL_START_MARK =       CHARS_TO_UINT32 ('P', '_', 's', 't');

static const pools_start_mark_t     POOLS_START_MARK =      CHARS_TO_UINT32 ('P', 'S', 's', 't');

/*------------------------------------------------------------------------------*/
winckel's avatar
winckel committed
150
static inline uint32_t items_group_number_items (items_group_t *items_group)
151
{
152
  return items_group->number_plus_one - 1;
winckel's avatar
winckel committed
153
154
155
156
}

static inline uint32_t items_group_free_items (items_group_t *items_group)
{
157
158
  items_group_positions_t positions;
  uint32_t                free_items;
winckel's avatar
winckel committed
159

160
  positions.all = items_group->positions.all;
161

162
163
  free_items = items_group->number_plus_one + positions.ind.put - positions.ind.get;
  free_items %= items_group->number_plus_one;
winckel's avatar
winckel committed
164

165
  return free_items;
winckel's avatar
winckel committed
166
167
168
169
}

static inline items_group_index_t items_group_get_free_item (items_group_t *items_group)
{
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  items_group_position_t  get_raw;
  items_group_position_t  put;
  items_group_position_t  get;
  items_group_position_t  free_items;

  items_group_index_t     index = ITEMS_GROUP_INDEX_INVALID;

  /* Get current put position */
  put = items_group->positions.ind.put % items_group->number_plus_one;
  /* Get current get position and increase it */
  get_raw = __sync_fetch_and_add (&items_group->positions.ind.get, 1);
  get = get_raw % items_group->number_plus_one;

  if(put == get) {
    /* No more item free, restore previous position */
    __sync_fetch_and_sub (&items_group->positions.ind.get, 1);
  } else {
    /* Get index at current get position */
    index = items_group->indexes[get];

    if (index <= ITEMS_GROUP_INDEX_INVALID) {
      /* Index has not yet been completely freed, restore previous get position */
      __sync_fetch_and_sub (&items_group->positions.ind.get, 1);
    } else {
      if (get_raw == items_group->number_plus_one) {
        /* Wrap get position */
        __sync_fetch_and_sub (&items_group->positions.ind.get, items_group->number_plus_one);
      }

      free_items = items_group_free_items(items_group);

      /* Updates minimum free items if needed */
      while (items_group->minimum > free_items) {
        items_group->minimum = free_items;
      }

      /* Clear index at current get position to indicate that item is free */
      items_group->indexes[get] = ITEMS_GROUP_INDEX_INVALID;
208
    }
209
  }
210

211
  return (index);
212
213
}

214
static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index)
215
{
216
217
  items_group_position_t  put_raw;
  items_group_position_t  put;
218

219
220
221
  /* Get current put position and increase it */
  put_raw = __sync_fetch_and_add (&items_group->positions.ind.put, 1);
  put = put_raw % items_group->number_plus_one;
222

223
224
225
226
  if (put_raw == items_group->number_plus_one) {
    /* Wrap position */
    __sync_fetch_and_sub (&items_group->positions.ind.put, items_group->number_plus_one);
  }
227

228
229
  AssertError (items_group->indexes[put] <= ITEMS_GROUP_INDEX_INVALID, return (EXIT_FAILURE),
               "Index at current put position (%d) is not marked as free (%d)!\n", put, items_group->number_plus_one);
230

231
232
233
  /* Save freed item index at current put position */
  items_group->indexes[put] = index;
  return (EXIT_SUCCESS);
234
}
235
236

/*------------------------------------------------------------------------------*/
237
static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle)
winckel's avatar
winckel committed
238
{
239
  memory_pools_t *memory_pools;
winckel's avatar
winckel committed
240

241
242
243
244
245
  /* Recover memory_pools */
  memory_pools = (memory_pools_t *) memory_pools_handle;
  /* Sanity check on passed handle */
  AssertError (memory_pools->start_mark == POOLS_START_MARK, memory_pools = NULL,
               "Handle %p is not a valid memory pools handle, start mark is missing!\n", memory_pools_handle);
winckel's avatar
winckel committed
246

247
  return (memory_pools);
winckel's avatar
winckel committed
248
249
}

250
static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle)
winckel's avatar
winckel committed
251
{
252
253
  void               *address;
  memory_pool_item_t *memory_pool_item;
winckel's avatar
winckel committed
254

255
256
257
  /* Recover memory_pools */
  address = memory_pool_item_handle - sizeof(memory_pool_item_start_t);
  memory_pool_item = (memory_pool_item_t *) address;
258

259
260
261
  /* Sanity check on passed handle */
  AssertError (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK, memory_pool_item = NULL,
               "Handle %p is not a valid memory pool item handle, start mark is missing!\n", memory_pool_item);
winckel's avatar
winckel committed
262

263
  return (memory_pool_item);
winckel's avatar
winckel committed
264
265
}

266
static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index)
winckel's avatar
winckel committed
267
{
268
  void               *address;
winckel's avatar
winckel committed
269

270
271
  address = (void *) memory_pool->items;
  address += index * memory_pool->pool_item_size;
winckel's avatar
winckel committed
272

273
  return (address);
winckel's avatar
winckel committed
274
}
275
276

/*------------------------------------------------------------------------------*/
277
memory_pools_handle_t memory_pools_create (uint32_t pools_number)
278
{
279
280
  memory_pools_t *memory_pools;
  pool_id_t       pool;
281

282
  AssertFatal (pools_number <= MAX_POOLS_NUMBER, "Too many memory pools requested (%d/%d)!\n", pools_number, MAX_POOLS_NUMBER); /* Limit to a reasonable number of pools */
283

284
285
286
  /* Allocate memory_pools */
  memory_pools = malloc (sizeof(memory_pools_t));
  AssertFatal (memory_pools != NULL, "Memory pools structure allocation failed!\n");
287

288
289
290
291
292
293
294
295
296
  /* Initialize memory_pools */
  {
    memory_pools->start_mark    = POOLS_START_MARK;
    memory_pools->pools_number  = pools_number;
    memory_pools->pools_defined = 0;

    /* Allocate pools */
    memory_pools->pools         = calloc (pools_number, sizeof(memory_pool_t));
    AssertFatal (memory_pools->pools != NULL, "Memory pools allocation failed!\n");
297

298
299
300
    /* Initialize pools */
    for (pool = 0; pool < pools_number; pool++) {
      memory_pools->pools[pool].start_mark = POOL_START_MARK;
301
    }
302
  }
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  return ((memory_pools_handle_t) memory_pools);
}

char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle)
{
  memory_pools_t     *memory_pools;
  pool_id_t           pool;
  char               *statistics;
  int                 printed_chars;
  uint32_t            allocated_pool_memory;
  uint32_t            allocated_pools_memory = 0;
  items_group_t      *items_group;
  uint32_t            pool_items_size;

  /* Recover memory_pools */
  memory_pools = memory_pools_from_handler (memory_pools_handle);
  AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);

  statistics = malloc(memory_pools->pools_defined * 200);

  printed_chars = sprintf (&statistics[0], "Pool:   size, number, minimum,   free, address space and memory used in Kbytes\n");

  for (pool = 0; pool < memory_pools->pools_defined; pool++) {
    items_group = &memory_pools->pools[pool].items_group_free;
    allocated_pool_memory = items_group_number_items (items_group) * memory_pools->pools[pool].pool_item_size;
    allocated_pools_memory += allocated_pool_memory;
    pool_items_size = memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t);
    printed_chars += sprintf (&statistics[printed_chars], "  %2u: %6u, %6u,  %6u, %6u, [%p-%p] %6u\n",
                              pool, pool_items_size,
                              items_group_number_items (items_group),
                              items_group->minimum,
                              items_group_free_items (items_group),
                              memory_pools->pools[pool].items,
                              ((void *) memory_pools->pools[pool].items) + allocated_pool_memory,
                              allocated_pool_memory / (1024));
  }

  printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024));

  return (statistics);
344
345
346
347
}

int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size)
{
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  memory_pools_t     *memory_pools;
  memory_pool_t      *memory_pool;
  pool_id_t           pool;
  items_group_index_t item_index;
  memory_pool_item_t *memory_pool_item;

  AssertFatal (pool_items_number <= MAX_POOL_ITEMS_NUMBER, "Too many items for a memory pool (%u/%d)!\n", pool_items_number, MAX_POOL_ITEMS_NUMBER); /* Limit to a reasonable number of items */
  AssertFatal (pool_item_size <= MAX_POOL_ITEM_SIZE, "Item size is too big for memory pool items (%u/%d)!\n", pool_item_size, MAX_POOL_ITEM_SIZE);   /* Limit to a reasonable item size */

  /* Recover memory_pools */
  memory_pools    = memory_pools_from_handler (memory_pools_handle);
  AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);

  /* Check number of already created pools */
  AssertFatal (memory_pools->pools_defined < memory_pools->pools_number, "Can not allocate more memory pool (%d)!\n", memory_pools->pools_number);

  /* Select pool */
  pool            = memory_pools->pools_defined;
  memory_pool     = &memory_pools->pools[pool];

  /* Initialize pool */
  {
    memory_pool->pool_id                            = pool;
    /* Item size in memory_pool_data_t items by excess */
    memory_pool->item_data_number                   = (pool_item_size + sizeof(memory_pool_data_t) - 1) / sizeof(memory_pool_data_t);
    memory_pool->pool_item_size                     = (memory_pool->item_data_number * sizeof(memory_pool_data_t)) + sizeof(memory_pool_item_t);
    memory_pool->items_group_free.number_plus_one   = pool_items_number + 1;
    memory_pool->items_group_free.minimum           = pool_items_number;
    memory_pool->items_group_free.positions.ind.put = pool_items_number;
    memory_pool->items_group_free.positions.ind.get = 0;

    /* Allocate free indexes */
    memory_pool->items_group_free.indexes = malloc(memory_pool->items_group_free.number_plus_one * sizeof(items_group_index_t));
    AssertFatal (memory_pool->items_group_free.indexes != NULL, "Memory pool indexes allocation failed!\n");

    /* Initialize free indexes */
    for (item_index = 0; item_index < pool_items_number; item_index++) {
      memory_pool->items_group_free.indexes[item_index] = item_index;
    }
387

388
389
    /* Last index is not allocated */
    memory_pool->items_group_free.indexes[item_index] = ITEMS_GROUP_INDEX_INVALID;
390

391
392
393
    /* Allocate items */
    memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size);
    AssertFatal (memory_pool->items != NULL, "Memory pool items allocation failed!\n");
winckel's avatar
winckel committed
394

395
396
397
398
399
400
401
    /* Initialize items */
    for (item_index = 0; item_index < pool_items_number; item_index++) {
      memory_pool_item                                      = memory_pool_item_from_index (memory_pool, item_index);
      memory_pool_item->start.start_mark                    = POOL_ITEM_START_MARK;
      memory_pool_item->start.pool_id                       = pool;
      memory_pool_item->start.item_status                   = ITEM_STATUS_FREE;
      memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK;
402
    }
403
  }
404

405
  memory_pools->pools_defined ++;
406

407
  return (0);
408
409
}

410
memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1)
winckel's avatar
winckel committed
411
{
412
413
414
415
416
  memory_pools_t             *memory_pools;
  memory_pool_item_t         *memory_pool_item;
  memory_pool_item_handle_t   memory_pool_item_handle = NULL;
  pool_id_t                   pool;
  items_group_index_t         item_index = ITEMS_GROUP_INDEX_INVALID;
winckel's avatar
winckel committed
417

418
#if defined(OAI_EMU) || defined(RTAI)
419
420
  vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC,
                                          __sync_or_and_fetch (&vcd_mp_alloc, 1L << info_0));
421
422
#endif

423
424
425
  /* Recover memory_pools */
  memory_pools = memory_pools_from_handler (memory_pools_handle);
  AssertError (memory_pools != NULL, {}, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
winckel's avatar
winckel committed
426

427
428
429
430
  for (pool = 0; pool < memory_pools->pools_defined; pool++) {
    if ((memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t)) < item_size) {
      /* This memory pool has too small items, skip it */
      continue;
431
    }
432
433
434
435
436
437
438
439
440

    item_index = items_group_get_free_item(&memory_pools->pools[pool].items_group_free);

    if (item_index <= ITEMS_GROUP_INDEX_INVALID) {
      /* Allocation failed, skip this pool */
      continue;
    } else {
      /* Allocation succeed, exit searching loop */
      break;
winckel's avatar
winckel committed
441
    }
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  }

  if (item_index > ITEMS_GROUP_INDEX_INVALID) {
    /* Convert item index into memory_pool_item address */
    memory_pool_item                    = memory_pool_item_from_index (&memory_pools->pools[pool], item_index);
    /* Sanity check on item status, must be free */
    AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_FREE, "Item status is not set to free (%d) in pool %u, item %d!\n",
                 memory_pool_item->start.item_status, pool, item_index);

    memory_pool_item->start.item_status = ITEM_STATUS_ALLOCATED;
    memory_pool_item->start.info[0]     = info_0;
    memory_pool_item->start.info[1]     = info_1;
    memory_pool_item_handle             = memory_pool_item->data;

    MP_DEBUG(" Alloc [%2u][%6d]{%6d}, %3u %3u, %6u, %p, %p, %p\n",
             pool, item_index,
             items_group_free_items (&memory_pools->pools[pool].items_group_free),
             info_0, info_1,
             item_size,
             memory_pools->pools[pool].items,
             memory_pool_item,
             memory_pool_item_handle);
  } else {
    MP_DEBUG(" Alloc [--][------]{------}, %3u %3u, %6u, failed!\n", info_0, info_1, item_size);
  }
winckel's avatar
winckel committed
467

468
#if defined(OAI_EMU) || defined(RTAI)
469
470
  vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC,
                                          __sync_and_and_fetch (&vcd_mp_alloc, ~(1L << info_0)));
471
472
#endif

473
  return memory_pool_item_handle;
winckel's avatar
winckel committed
474
475
}

476
int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0)
winckel's avatar
winckel committed
477
{
478
479
480
481
482
483
484
485
  memory_pools_t     *memory_pools;
  memory_pool_item_t *memory_pool_item;
  pool_id_t           pool;
  items_group_index_t item_index;
  uint32_t            item_size;
  uint32_t            pool_item_size;
  uint16_t            info_1;
  int                 result;
winckel's avatar
winckel committed
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  /* Recover memory_pools */
  memory_pools = memory_pools_from_handler (memory_pools_handle);
  AssertError (memory_pools != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pools for handle %p!\n", memory_pools_handle);

  /* Recover memory pool item */
  memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
  AssertError (memory_pool_item != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);

  info_1 = memory_pool_item->start.info[1];

#if defined(OAI_EMU) || defined(RTAI)
  vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE,
                                          __sync_or_and_fetch (&vcd_mp_free, 1L << info_1));
#endif

  /* Recover pool index */
  pool = memory_pool_item->start.pool_id;
  AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);

  item_size = memory_pools->pools[pool].item_data_number;
  pool_item_size = memory_pools->pools[pool].pool_item_size;
  item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
509

510
511
512
513
514
515
  MP_DEBUG(" Free  [%2u][%6d]{%6d}, %3u %3u,         %p, %p, %p, %u\n",
           pool, item_index,
           items_group_free_items (&memory_pools->pools[pool].items_group_free),
           memory_pool_item->start.info[0], info_1,
           memory_pool_item_handle, memory_pool_item,
           memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  /* Sanity check on calculated item index */
  AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
               "Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
               memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
  /* Sanity check on end marker, must still be present (no write overflow) */
  AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
               "Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
  /* Sanity check on item status, must be allocated */
  AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
               "Trying to free a non allocated (%x) memory pool item (pool %u, item %d)!\n",
               memory_pool_item->start.item_status, pool, item_index);

  memory_pool_item->start.item_status = ITEM_STATUS_FREE;

  result = items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index);

  AssertError (result == EXIT_SUCCESS, {}, "Failed to free memory pool item (pool %u, item %d)!\n", pool, item_index);
534
535

#if defined(OAI_EMU) || defined(RTAI)
536
537
  vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE,
                                          __sync_and_and_fetch (&vcd_mp_free, ~(1L << info_1)));
538
539
#endif

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  return (result);
}

void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info)
{
  memory_pools_t     *memory_pools;
  memory_pool_item_t *memory_pool_item;
  pool_id_t           pool;
  items_group_index_t item_index;
  uint32_t            item_size;
  uint32_t            pool_item_size;

  AssertFatal (index < MEMORY_POOL_ITEM_INFO_NUMBER, "Incorrect info index (%d/%d)!\n", index, MEMORY_POOL_ITEM_INFO_NUMBER);

  /* Recover memory pool item */
  memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
  AssertFatal (memory_pool_item != NULL, "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);

  /* Set info[1] */
  memory_pool_item->start.info[index] = info;

  /* Check item validity and log (not mandatory) */
  if (1) {
    /* Recover memory_pools */
    memory_pools = memory_pools_from_handler (memory_pools_handle);
    AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);

winckel's avatar
winckel committed
567
568
    /* Recover pool index */
    pool = memory_pool_item->start.pool_id;
569
    AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
winckel's avatar
winckel committed
570

571
572
573
574
    item_size = memory_pools->pools[pool].item_data_number;
    pool_item_size = memory_pools->pools[pool].pool_item_size;
    item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;

575
    MP_DEBUG(" Info  [%2u][%6d]{%6d}, %3u %3u,         %p, %p, %p, %u\n",
winckel's avatar
winckel committed
576
577
             pool, item_index,
             items_group_free_items (&memory_pools->pools[pool].items_group_free),
578
             memory_pool_item->start.info[0], memory_pool_item->start.info[1],
579
             memory_pool_item_handle, memory_pool_item,
winckel's avatar
winckel committed
580
             memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
581

winckel's avatar
winckel committed
582
    /* Sanity check on calculated item index */
583
584
    AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
                 "Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
winckel's avatar
winckel committed
585
                 memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
586
    /* Sanity check on end marker, must still be present (no write overflow) */
587
588
    AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
                 "Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
589
    /* Sanity check on item status, must be allocated */
590
    AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
591
                 "Trying to free a non allocated (%x) memory pool item (pool %u, item %d)\n",
winckel's avatar
winckel committed
592
                 memory_pool_item->start.item_status, pool, item_index);
593
  }
winckel's avatar
winckel committed
594
}