idm.c 1.32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/*
 *	BIRD Library -- ID Map
 *
 *	(c) 2013--2015 Ondrej Zajicek <santiago@crfreenet.org>
 *	(c) 2013--2015 CZ.NIC z.s.p.o.
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include <stdlib.h>

#include "nest/bird.h"
#include "lib/idm.h"
#include "lib/resource.h"
#include "lib/string.h"


void
idm_init(struct idm *m, pool *p, uint size)
{
  m->pos = 0;
  m->used = 1;
  m->size = size;
  m->data = mb_allocz(p, m->size * sizeof(u32));

  /* ID 0 is reserved */
  m->data[0] = 1;
}

static inline int u32_cto(uint x) { return ffs(~x) - 1; }

u32
idm_alloc(struct idm *m)
{
  uint i, j;

  for (i = m->pos; i < m->size; i++)
    if (m->data[i] != 0xffffffff)
      goto found;

  /* If we are at least 7/8 full, expand */
  if (m->used > (m->size * 28))
  {
    m->size *= 2;
    m->data = mb_realloc(m->data, m->size * sizeof(u32));
    memset(m->data + i, 0, (m->size - i) * sizeof(u32));
    goto found;
  }

  for (i = 0; i < m->pos; i++)
    if (m->data[i] != 0xffffffff)
      goto found;

  ASSERT(0);

56
found:
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
  ASSERT(i < 0x8000000);

  m->pos = i;
  j = u32_cto(m->data[i]);

  m->data[i] |= (1 << j);
  m->used++;
  return 32 * i + j;
}

void
idm_free(struct idm *m, u32 id)
{
  uint i = id / 32;
  uint j = id % 32;

  ASSERT((i < m->size) && (m->data[i] & (1 << j)));
  m->data[i] &= ~(1 << j);
  m->used--;
}