packed.c 7.53 KB
#include <stdlib.h>
#include <string.h>

#ifdef USE_MMAP
#include <sys/mman.h>
#endif

#include <assert.h>

#include "fdc_int.h"
#include "constraints.h"
#include "packed.h"

static struct _fd_packed_problem *packed_memory; // XXX: so it can be freed
#ifdef USE_MMAP
static size_t packed_memory_size;
#endif

static struct _fd_packed_problem *_fd_allocate_memory()
{
  struct _fd_packed_problem *p;
  int tvars, tconstr, tconsts;
  int i;

  if ((p  = malloc(sizeof(*p))) == NULL)
    return NULL;

  packed_memory = p; // XXX

  p->nvariables = fd_variables_count;
  p->variables = calloc(p->nvariables, sizeof(*p->variables)); // XXX: NULL
  p->nconstraints = _fd_constraint_count;
  p->constraints = calloc(p->nconstraints, sizeof(*p->constraints)); // XXX: NULL

  tvars = tconstr = tconsts = 0;
  for (i = 0; i < fd_variables_count; ++i)
    tconstr += _fd_variables[i]->nconstraints;

  for (i = 0; i < _fd_constraint_count; ++i)
    {
      tvars += _fd_constraints[i]->nvariables;
      tconsts += _fd_constraints[i]->nconstants;
    }

  _fd_debug("packed size is %d + %d + %d + %d\n",
	    sizeof(*p),
	    p->nvariables * sizeof(*p->variables),
	    p->nconstraints * sizeof(*p->constraints),
	    p->nvariables * sizeof(struct _fd_packed_int) +
	    p->nconstraints * sizeof(struct _fd_packed_constraint) +
	    tvars * sizeof(fd_int) + tconstr * sizeof(fd_constraint) +
	    tconsts * sizeof(int));

  p->data = malloc(p->nvariables * sizeof(struct _fd_packed_int) + // XXX
		   p->nconstraints * sizeof(struct _fd_packed_constraint) + // XXX
		   tvars * sizeof(fd_int) + // XXX: ?
		   tconstr * sizeof(fd_constraint) + // XXX: ?
		   tconsts * sizeof(int)); // XXX: NULL

  if (p->variables == NULL || p->constraints == NULL || p->data == NULL)
    {
      free(p->variables);
      free(p->constraints);
      free(p->data);
      free(p);

      return NULL;
    }

#ifdef USE_MMAP
  {
    void *m;

    packed_memory_size = sizeof(*p) +
      p->nvariables * sizeof(*p->variables) +
      p->nconstraints * sizeof(*p->constraints) +
      (p->nvariables * sizeof(struct _fd_packed_int) +
       p->nconstraints * sizeof(struct _fd_packed_constraint) +
       tvars * sizeof(fd_int) + tconstr * sizeof(fd_constraint) +
       tconsts * sizeof(int));

    m = mmap(NULL, packed_memory_size,
	     PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    if (m == MAP_FAILED)
      {
	perror("mmap");

	_fd_fatal("mmap() failed");
      }

    p = m;

    memcpy(p, packed_memory, sizeof(*packed_memory));
    p->variables = m + sizeof(*packed_memory);
    p->constraints =
      m + sizeof(*packed_memory) + p->nvariables * sizeof(*p->variables);
    p->data = m + sizeof(*packed_memory) +
      p->nvariables * sizeof(*p->variables) +
      p->nconstraints * sizeof(*p->constraints);

    free(packed_memory->variables);
    free(packed_memory->constraints);
    free(packed_memory->data);
    free(packed_memory);

    packed_memory = p;
  }
#endif

  return p;
}

void _fd_free_packed_memory()
{
#ifndef USE_MMAP
  free(packed_memory->variables);
  free(packed_memory->constraints);
  free(packed_memory->data);
  free(packed_memory);
#else
  munmap(packed_memory, packed_memory_size);
#endif
}

/* find index of CONSTRAINT in _fd_constraints */
// XXX!
int _fd_locate(fd_constraint constraint)
{
  int i = 0;

  while (_fd_constraints[i] != constraint)
    i++;

  return i;
}

void _fd_pack_problem()
{
  struct _fd_packed_problem *packed;
  int offset;
  int i, j;

#ifndef CONSTRAINT_CLASS
  _fd_fatal("packed problems require CONSTRAINT_CLASS");
#endif

  packed = _fd_allocate_memory();

  assert(packed != NULL); // XXX

  offset = 0;

  // start copying the variables
  for (i = 0; i < packed->nvariables; ++i)
    {
      void *address = packed->data + offset; // XXX: void* instead of byte*?

#ifdef USE_OFFSET
      packed->variables[i] = offset;
#else
      packed->variables[i] = address;
#endif
      memcpy(address, _fd_variables[i], sizeof(struct _fd_packed_int)); // XXX

      // reserve space for the variable's constraints
      offset += sizeof(struct _fd_packed_int);
      address += sizeof(struct _fd_packed_int);
#ifdef USE_OFFSET
      ((struct _fd_packed_int *) (packed->data + packed->variables[i]))->constraints = address; // XXX: -> offset
#else
      packed->variables[i]->constraints = address; // XXX: -> offset
#endif

//      offset += packed->variables[i]->nconstraints * sizeof(VAR_C_T *); // XXX: ->offset
      offset += _fd_variables[i]->nconstraints * sizeof(VAR_C_T *); // XXX: ->offset
    }

  // copy the constraints
  for (i = 0; i < packed->nconstraints; ++i)
    {
      void *address = packed->data + offset; // XXX: void* instead of byte*?

#ifdef USE_OFFSET
      packed->constraints[i] = offset;
#else
      packed->constraints[i] = address;
#endif
      memcpy(address, _fd_constraints[i], sizeof(struct _fd_packed_constraint)); // XXX

      // reserve space for the constraint's variables
      offset += sizeof(struct _fd_packed_constraint);
      address += sizeof(struct _fd_packed_constraint);
#ifdef USE_OFFSET
      ((struct _fd_packed_constraint *) (packed->data + packed->constraints[i]))->variables = address; // XXX: -> offset
#else
      packed->constraints[i]->variables = address; // XXX: -> offset
#endif

      // reserve space for the constraint's constants
      offset += _fd_constraints[i]->nvariables * sizeof(C_VAR_T *);
      address += _fd_constraints[i]->nvariables * sizeof(C_VAR_T *);

      if (_fd_constraints[i]->nconstants)
	{
#ifdef USE_OFFSET
	  ((struct _fd_packed_constraint *) (packed->data + packed->constraints[i]))->constants = address; // XXX: -> offset
#else
	  packed->constraints[i]->constants = address; // XXX: -> offset
#endif

//          offset += packed->constraints[i]->nconstants * sizeof(int);
	  offset += _fd_constraints[i]->nconstants * sizeof(int);
	}

      // copy the constraint's variables
//      for (j = 0; j < packed->constraints[i]->nvariables; ++j)
      for (j = 0; j < _fd_constraints[i]->nvariables; ++j)
#ifdef USE_OFFSET
	((struct _fd_packed_constraint *) (packed->data + packed->constraints[i]))->variables[j] =
#else
	packed->constraints[i]->variables[j] =
#endif
	  _fd_constraints[i]->variables[j]; // XXX: could be done with memcpy();

      // copy the constraint's constants
//      for (j = 0; j < packed->constraints[i]->nconstants; ++j)
      for (j = 0; j < _fd_constraints[i]->nconstants; ++j)
#ifdef USE_OFFSET
	((struct _fd_packed_constraint *) (packed->data + packed->constraints[i]))->constants[j] = _fd_constraints[i]->constants[j];
#else
	packed->constraints[i]->constants[j] = _fd_constraints[i]->constants[j];
#endif
    }

  // copy the variables' constraints
  for (i = 0; i < packed->nvariables; ++i)
//    for (j = 0; j < packed->variables[i]->nconstraints; ++j)
    for (j = 0; j < _fd_variables[i]->nconstraints; ++j)
#ifdef USE_OFFSET
      ((struct _fd_packed_int *) (packed->data + packed->variables[i]))->constraints[j] =
#else
      packed->variables[i]->constraints[j] =
#endif
        _fd_variables[i]->constraints[j]; // XXX: could be done with memcpy();

#ifdef USE_MMAP
  if (mprotect(packed, packed_memory_size, PROT_READ))
    perror("mprotect");
#endif


  // XXX: DANGER!!!!!!!!!

#ifndef USE_STORE
  // update address of the domains of the variables (for external access)
  for (i = 0; i < fd_variables_count; ++i)
    _fd_variables[i]->domain = packed->variables[i]->domain;
#endif

  // XXX: should make these point into packed_memory
  memcpy(_fd_variables, packed->variables, fd_variables_count * sizeof(fd_int));
  memcpy(_fd_constraints, packed->constraints, _fd_constraint_count * sizeof(fd_constraint));
}