#include #include #ifdef USE_MMAP #include #endif #include #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)); }