VOID PutJob(INT xs, INT ys, INT xe, INT ye, INT xbe, INT ybe, INT pid) { INT i, j; INT xb_addr, yb_addr; /* Bundle pixel address. */ INT xb_end, yb_end; /* End bundle pixels. */ INT xb_size, yb_size; /* Bundle size. */ WPJOB *wpentry; /* New work pool entry. */ /* Starting block pixel address (upper left pixel). */ xb_addr = xs; yb_addr = ys; /* Ending block pixel address (lower right pixel). */ xb_end = xb_addr + xe - 1; yb_end = yb_addr + ye - 1; for (i = 0; i < ye; i += ybe) { for (j = 0; j < xe; j += xbe) { /* Determine bundle size. */ if ((xb_addr + xbe - 1) <= xb_end) xb_size = xbe; else xb_size = xb_end - xb_addr + 1; if ((yb_addr + ybe - 1) <= yb_end) yb_size = ybe; else yb_size = yb_end - yb_addr + 1; /* Initialize work pool entry. */ wpentry = (WPJOB*)GlobalMalloc(sizeof(WPJOB), "workpool.c"); wpentry->xpix = xb_addr; wpentry->ypix = yb_addr; wpentry->xdim = xb_size; wpentry->ydim = yb_size; /* Add to top of work pool stack. */ if (!gm->workpool[pid][0]) wpentry->next = NULL; else wpentry->next = gm->workpool[pid][0]; gm->workpool[pid][0] = wpentry; xb_addr += xbe; } xb_addr = xs; yb_addr += ybe; } }
VOID SphRead(OBJECT *po, FILE *pf) { INT i; INT instat; /* Input counter */ SPHERE *ps; /* Ptr to sphere data. */ ELEMENT *pe; /* Ptr to sphere element. */ pe = po->pelem; ps = (SPHERE*)GlobalMalloc(sizeof(SPHERE)*po->numelements, "sph.c"); for (i = 0; i < po->numelements; i++) { instat = fscanf(pf,"%lf %lf %lf %lf", &(ps->center[0]), &(ps->center[1]), &(ps->center[2]), &(ps->rad)); if (instat != 4) { printf("Error in SphRead: sphere %ld.\n", i); exit(1); } ps->center[3] = 1.0; /* w initialization. */ ps->rad2 = ps->rad*ps->rad; pe->data = (CHAR *)ps; pe->parent = po; SphElementBoundBox(pe, ps); ps++; pe++; } }
VOID *GlobalCalloc(UINT n, UINT size) { UINT nbytes; UINT huge *p; VOID huge *q; nbytes = ROUND_UP(n*size); p = q = GlobalMalloc(nbytes, "GlobalCalloc"); nbytes >>= 2; /* Need size in words. */ while (nbytes--) *p++ = 0; return (q); }
VOID PolyRead(OBJECT *po, FILE *pf) { INT i, j; /* Indices. */ INT instat; /* Read status. */ INT *vindex; INT totalverts; /* Total # of vertices in poly mesh. */ CHAR normstr[5]; /* Face/vertex normal flag string. */ BOOL pnormals; /* Face normals present? */ VEC3 pnorm; /* Polygon normal accumulator. */ VEC3 *vlist, *vptr, *vp; /* Ptr to vertex list. */ VEC3 *vptmp, *vptmp2; /* Ptr to vertex list. */ VEC3 tmppnt, tmppnt2, cross; POLY *pp; /* Ptr to polygon data. */ ELEMENT *pe; /* Ptr to polygon element. */ pe = po->pelem; /* Allocate space for object data. */ instat = fscanf(pf, "%ld", &totalverts); if (instat != 1) { printf("Error in PolyRead: totalverts.\n"); exit(-1); } pp = GlobalMalloc(sizeof(POLY)*po->numelements, "poly.c"); vlist = GlobalMalloc(sizeof(VEC3)*(totalverts + 1), "poly.c"); vptr = vlist; /* Are polygon face normals supplied? */ instat = fscanf(pf, "%s\n", normstr); if (instat != 1) { printf("Error in PolyRead: face normal indicator.\n"); exit(-1); } pnormals = (normstr[2] == 'y' ? TRUE : FALSE); /* Read vertex list. */ for (i = 0; i < totalverts; i++) { instat = fscanf(pf, "%lf %lf %lf", &(*vptr)[0], &(*vptr)[1], &(*vptr)[2]); if (instat != 3) { printf("Error in PolyRead: vertex %ld.\n", i); exit(-1); } vptr++; } (*vptr)[0] = HUGE_REAL; (*vptr)[1] = HUGE_REAL; (*vptr)[2] = HUGE_REAL; /* Read polygon list. */ for (i = 0; i < po->numelements; i++) { instat = fscanf(pf, "%ld", &(pp->nverts)); if (instat != 1) { printf("Error in PolyRead: vertex count.\n"); exit(-1); } if (pp->nverts > MAX_VERTS) { printf("Polygon vertex count, %ld, exceeds maximum.\n", pp->nverts); exit(-1); } if (pnormals) { instat = fscanf(pf, " %lf %lf %lf", &(pp->norm[0]), &(pp->norm[1]), &(pp->norm[2])); if (instat != 3) { printf("Error in PolyRead: face normal %ld.\n", i); exit(-1); } } pp->vptr = vlist; pp->vindex = GlobalMalloc(sizeof(INT)*pp->nverts, "poly.c"); vindex = pp->vindex; for (j = 0; j < pp->nverts; j++) { instat = fscanf(pf, "%ld", vindex++); if (instat != 1) { printf("Error in PolyRead: vertex index %ld.\n", i); exit(-1); } } /* If not supplied, calculate plane normal. */ vindex = pp->vindex; vptr = vlist; if (!pnormals) { vp = vptr + (*vindex); VecZero(pnorm); for (j = 0; j < pp->nverts - 2; j++) { vptmp = vptr + (*(vindex + 1)); vptmp2 = vptr + (*(vindex + 2)); VecSub(tmppnt, (*vptmp), (*vp)); VecSub(tmppnt2, (*vptmp2), (*vptmp)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); vp = vptmp; vindex += 1; } VecSub(tmppnt, (*vptmp2), (*vp)); vindex = pp->vindex; vp = vptr + (*vindex); VecSub(tmppnt2, (*vp), (*vptmp2)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); vp = vptr + (*vindex); VecSub(tmppnt, (*vp), (*vptmp2)); vptmp = vptr + (*(vindex + 1)); VecSub(tmppnt2, (*vptmp), (*vp)); VecCross(cross, tmppnt, tmppnt2); VecAdd(pnorm, pnorm, cross); VecScale(pp->norm, 1.0/VecLen(pnorm), pnorm); } /* Calculate plane equation d. */ vp = pp->vptr + *(pp->vindex); pp->d = -(pp->norm[0]*(*vp)[0] + pp->norm[1]*(*vp)[1] + pp->norm[2]*(*vp)[2]); pe->data = (CHAR *)pp; pe->parent = po; PolyElementBoundBox(pe, pp); pp++; pe++; } }
VOID InitEnv() { /* Default eye position. */ View.eye[0] = 0.5; View.eye[1] = 0.5; View.eye[2] = -1.5; /* Default center position. */ View.coi[0] = 0.5; View.coi[1] = 0.5; View.coi[2] = 0.5; /* Default background color. */ View.bkg[0] = 0.0; View.bkg[1] = 0.0; View.bkg[2] = 0.8; /* Default viewing angle. */ View.vang = 60.0; /* Default ambient light. */ View.ambient[0] = 0.1; View.ambient[1] = 0.1; View.ambient[2] = 0.1; /* Shadows and shading. */ View.shad = TRUE; View.shading = TRUE; /* Perspective projection. */ View.projection = PT_PERSP; /* Default resolution is 100 x 100 */ Display.xres = 100; Display.yres = 100; Display.numpixels = 100*100; /* Default maximum raytrace level. */ Display.maxlevel = 5; /* Default anti-aliasing. */ Display.maxAAsubdiv = 0; Display.aatolerance = .020; Display.aarow = MAX_AA_ROW - 1; Display.aacol = MAX_AA_COL - 1; /* Default ray minimum weight is 0.001. */ Display.minweight = 0.001; /* Default screen size. */ Display.scrDist = 164.5; Display.scrWidth = 190.0; Display.scrHeight = 190.0; Display.scrHalfWidth = Display.scrWidth * 0.5; Display.scrHalfHeight = Display.scrHeight* 0.5; Display.vWscale = Display.scrWidth/(REAL)Display.xres; Display.vHscale = Display.scrHeight/(REAL)Display.yres; /* Init transformation matrices. */ MatrixIdentity(View.vtrans); MatrixIdentity(View.model); GeoFile = FALSE; PicFile = FALSE; ModelNorm = TRUE; ModelTransform = FALSE; DataType = DT_ASCII; TraversalType = TT_LIST; /* Init statistics. * * Stats.total_rays = 0; * Stats.prim_rays = 0; * Stats.shad_rays = 0; * Stats.shad_rays_not_hit = 0; * Stats.shad_rays_hit = 0; * Stats.shad_coherence_rays = 0; * Stats.refl_rays = 0; * Stats.trans_rays = 0; * Stats.aa_rays = 0; * Stats.bound_tests = 0; * Stats.bound_hits = 0; * Stats.bound_misses = 0; * Stats.ray_obj_hit = 0; * Stats.ray_obj_miss = 0; * Stats.max_tree_depth = 0; * Stats.max_objs_ray = 0; * Stats.max_rays_pixel = 0; * Stats.max_objs_pixel = 0; * Stats.total_objs_tested = 0; * Stats.coverage = 0; */ lights = GlobalMalloc(sizeof(LIGHT), "env.c"); bundlex = 25; bundley = 25; blockx = 2; blocky = 2; }
VOID ReadEnvFile(CHAR *EnvFileName) { INT i, j; /* Indices. */ INT stat; /* Input var status counter. */ INT dummy; CHAR opcode; /* Environment spec opcode. */ CHAR command[30]; /* Environment spec command. */ CHAR opparam[30]; /* Command parameter. */ CHAR dummy_char[60]; CHAR datafile[10]; BOOL lights_set; /* Lights set? */ FILE *pf; /* Input file pointer. */ LIGHT *lptr, *lastlight; /* Light node pointers. */ /* Open command file. */ pf = fopen(EnvFileName, "r"); if (!pf) { printf("Unable to open environment file %s.\n", EnvFileName); exit(-1); } InitEnv(); /* Set defaults. */ nlights = 0; lights_set = FALSE; /* Process command file according to opcodes. */ while (fscanf(pf, "%s", command) != EOF) { opcode = LookupCommand(command); switch (opcode) { /* Eye position. */ case OP_EYE: stat = fscanf(pf, "%lf %lf %lf", &(View.eye[0]), &(View.eye[1]), &(View.eye[2])); if (stat != 3) { printf("error: eye position.\n"); exit(-1); } break; /* Center of interest position. */ case OP_COI: stat = fscanf(pf, "%lf %lf %lf", &(View.coi[0]), &(View.coi[1]), &(View.coi[2])); if (stat != 3) { printf("error: coi position.\n"); exit(-1); } break; /* Background color. */ case OP_BKGCOL: stat = fscanf(pf, "%lf %lf %lf", &(View.bkg[0]), &(View.bkg[1]), &(View.bkg[2])); if (stat != 3) { printf("error: background color.\n"); exit(-1); } if (!VerifyColorRange(View.bkg)) exit(-1); break; /* Viewing angle in degrees. */ case OP_VANG: stat = fscanf(pf, "%lf", &(View.vang)); if (stat != 1) { printf("error: viewing angle.\n"); exit(-1); } if (View.vang < 0.0 || View.vang > 100.0) { printf("Invalid angle %f.\n", View.vang); exit(-1); } break; /* Ambient. */ case OP_AMBIENT: stat = fscanf(pf, "%lf %lf %lf", &(View.ambient[0]), &(View.ambient[1]), &(View.ambient[2])); if (stat != 3) { printf("error: ambient.\n"); exit(-1); } if (!VerifyColorRange(View.ambient)) exit(-1); break; /* Anti-aliasing level. */ case OP_ANTILEVEL: stat = fscanf(pf, "%ld", &(Display.maxAAsubdiv)); if (stat != 1) { printf("View error: antialias level.\n"); exit(-1); } if (Display.maxAAsubdiv < 0 || Display.maxAAsubdiv > 3) { printf("error: antialias level %ld.\n", Display.maxAAsubdiv); exit(-1); } break; /* Recursion level. */ case OP_MAXLEVEL: stat = fscanf(pf, "%ld", &(Display.maxlevel)); printf("maxlevel of ray recursion = %ld\n",Display.maxlevel); fflush(stdout); if (stat != 1) { printf("error: recursion level.\n"); exit(-1); } if (Display.maxlevel > 5 || Display.maxlevel < 0) { printf("error: recursion level %ld.\n", Display.maxlevel); exit(-1); } break; /* Mininum ray weight. */ case OP_MINWEIGHT: stat = fscanf(pf, "%lf", &(Display.minweight)); if (stat != 1) { printf("error: miniumum ray weight.\n"); exit(-1); } if (Display.minweight < 0.0 || Display.minweight > 1.0) { printf("error: invalid ray weight %f.\n", Display.minweight); exit(-1); } break; /* Anti tolerance weight. */ case OP_ANTITOL: stat = fscanf(pf, "%lf", &(Display.aatolerance)); if (stat != 1) { printf("error: anti tolerance weight.\n"); exit(-1); } if (Display.aatolerance < 0.0 || Display.aatolerance > 1.0) { printf("error: invalid anti tolerance weight %f.\n", Display.aatolerance); exit(-1); } break; /* Resolution. */ case OP_RES: stat = fscanf(pf, "%ld %ld", &(Display.xres), &(Display.yres)); if (stat != 2) { printf("error: resolution.\n"); exit(-1); } break; /* Light positions and colors. */ case OP_LIGHT: lights_set = TRUE; if (nlights > 0) lptr = GlobalMalloc(sizeof(LIGHT), "env.c"); else lptr = lights; stat = fscanf(pf, "%lf %lf %lf %lf %lf %lf", &(lptr->pos[0]), &(lptr->pos[1]), &(lptr->pos[2]), &(lptr->col[0]), &(lptr->col[1]), &(lptr->col[2])); if (stat != 6) { printf("error: Lights.\n"); exit(-1); } if (!VerifyColorRange(lptr->col)) exit(-1); lptr->pos[3] = 1.0; stat = fscanf(pf, "%ld", &(lptr->shadow)); if (stat != 1) { printf("error: Lights shadow indicator.\n"); exit(-1); } lptr->next = NULL; if (nlights > 0) lastlight->next = lptr; nlights++; lastlight = lptr; break; /* Model transformation matrix. */ case OP_MODELMAT: for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { stat = fscanf(pf, "%lf", &(View.model[i][j])); if (stat != 1) { printf("Error in matrix.\n"); exit(-1); } } ModelTransform = TRUE; break; /* Shadow info. */ case OP_SHAD: stat = fscanf(pf, "%s", opparam); if (stat != 1) { printf("error: shadow.\n"); exit(-1); } if (strcmp(opparam, "on") == 0) View.shad = TRUE; else View.shad = FALSE; break; /* Shading info. */ case OP_SHADING: stat = fscanf(pf, "%s", opparam); if (stat != 1) { printf("error: shading %s.\n", opparam); exit(-1); } if (strcmp(opparam, "on") == 0) View.shading = TRUE; else View.shading = FALSE; break; /* Projection type. */ case OP_PROJECT: stat = fscanf(pf, "%s", opparam); if (stat != 1) { printf("error: projection %s.\n", opparam); exit(-1); } if (strcmp(opparam, "perspective") == 0) View.projection = PT_PERSP; else if (strcmp(opparam, "orthographic") == 0) View.projection = PT_ORTHO; else { printf("Invalid projection %s.\n", opparam); exit(-1); } break; /* Database traversal info. */ case OP_TRAVERSAL: stat = fscanf(pf, "%s", opparam); if (stat != 1) { printf("error: traversal %s.\n", opparam); exit(-1); } if (strcmp(opparam, "list") == 0) TraversalType = TT_LIST; else if (strcmp(opparam, "huniform") == 0) TraversalType = TT_HUG; else { printf("Invalid traversal code %s.\n", opparam); exit(-1); } break; /* Geometry file. */ case OP_GEOM_FILE: stat = fscanf(pf, " %s", GeoFileName); if (stat != 1) { printf("error: geometry file.\n"); exit(-1); } GeoFile = TRUE; break; /* Runlength file. */ case OP_RL_FILE: stat = fscanf(pf, " %s", PicFileName); if (stat != 1) { printf("error: runlength file.\n"); exit(-1); } PicFile = TRUE; break; case OP_PREVIEW_BKCULL: stat = fscanf(pf, "%ld", &dummy); if (stat != 1) { printf("error: Preview bkcull.\n"); exit(-1); } break; case OP_PREVIEW_FILL: stat = fscanf(pf, "%ld", &dummy); if (stat != 1) { printf("error: Preview fill.\n"); exit(-1); } break; case OP_PREVIEW_SPHTESS: stat = fscanf(pf, "%s", dummy_char); if (stat != 1) { printf("error: sphere tess.\n"); exit(-1); } break; case OP_NORM_DB: stat = fscanf(pf, "%s", opparam); if (stat != 1) { printf("error: norm database.\n"); exit(-1); } if (strcmp(opparam, "no") == 0) ModelNorm = FALSE; break; case OP_DATA_TYPE: stat = fscanf(pf, "%s", datafile); if (stat != 1) { printf("error: datatype.\n"); exit(-1); } if (strcmp(datafile, "binary") == 0) DataType = DT_BINARY; break; case OP_HU_MAX_PRIMS_CELL: stat = fscanf(pf, "%ld", &hu_max_prims_cell); if (stat != 1) { printf("error: Huniform prims per cell.\n"); exit(-1); } break; case OP_HU_GRIDSIZE: stat = fscanf(pf, "%ld", &hu_gridsize); if (stat != 1) { printf("error: Huniform gridsize.\n"); exit(-1); } break; case OP_HU_NUMBUCKETS: stat = fscanf(pf, "%ld", &hu_numbuckets); if (stat != 1) { printf("error: Huniform numbuckets.\n"); exit(-1); } break; case OP_HU_MAX_SUBDIV: stat = fscanf(pf, "%ld", &hu_max_subdiv_level); if (stat != 1 || hu_max_subdiv_level > 3) { printf("error: Huniform max subdiv level.\n"); exit(-1); } break; case OP_HU_LAZY: stat = fscanf(pf, "%ld", &hu_lazy); if (stat != 1) { printf("error: Huniform lazy.\n"); exit(-1); } break; case OP_BUNDLE: stat = fscanf(pf, "%ld %ld", &bundlex, &bundley); if (stat != 2 ) { printf("error: bundle.\n"); exit(-1); } break; case OP_BLOCK: stat = fscanf(pf, "%ld %ld", &blockx, &blocky); if (stat != 2 ) { printf("error: block.\n"); exit(-1); } break; default: printf("Warning: unrecognized env command: %s.\n", command); break; } } fclose(pf); /* Display parameters reset. */ Display.numpixels = Display.xres*Display.yres; Display.vWscale = Display.scrWidth/Display.xres; Display.vHscale = Display.scrHeight/Display.yres; /* If no light information given, set default. */ if (!lights_set) InitLights(); /* Set up screen parameters. */ InitDisplay(); /* Parameter check; think about lifting this restriction. */ if ((TraversalType != TT_LIST) && ModelNorm == FALSE) { printf("Data must be normalized with this traversal method!.\n"); ModelNorm = TRUE; } }
VOID ReadGeoFile(CHAR *GeoFileName) { INT i; INT dummy; INT stat; /* Input read counter. */ CHAR comchar; CHAR primop; /* Primitive opcode. */ CHAR objstr[NAME_LEN]; /* Object descriptions. */ CHAR objname[NAME_LEN]; FILE *pf; /* Ptr to geo file desc. */ SURF *ps; /* Ptr to surface desc. */ MATRIX model; /* Model matrix. */ MATRIX modelInv; /* Model matrix inverse. */ MATRIX modelInvT; /* Model matrix inv transpose*/ OBJECT *prev; /* Ptr to previous object. */ OBJECT *curr; /* Ptr to current object. */ ELEMENT *pe; /* Ptr to the element list. */ /* Open the model file. */ pf = fopen(GeoFileName, "r"); if (!pf) { printf("Unable to open model file %s.\n", GeoFileName); exit(1); } /* Initialize pointers and counters. */ curr = NULL; prev = NULL; gm->modelroot = NULL; prim_obj_cnt = 0; prim_elem_cnt = 0; /* Retrieve model transform. */ MatrixCopy(model, View.model); MatrixInverse(modelInv, model); MatrixTranspose(modelInvT, modelInv); /* Check for comments. */ if ((comchar = getc(pf)) != '#') ungetc(comchar, pf); else { comchar = '\0'; /* Set to other than '#'. */ while (comchar != '#') if ((comchar = getc(pf)) == EOF) { fprintf(stderr, "Incorrect comment in geometry file.\n"); exit(-1); } } /* Process the file data for each object. */ while ((stat = fscanf(pf, "%s %s", objstr, objname)) != EOF) { if (stat != 2 || strcmp(objstr, "object") != 0) { printf("Invalid object definition %s.\n", objstr); exit(-1); } /* Allocate next object and set list pointers. */ prim_obj_cnt++; curr = GlobalMalloc(sizeof(OBJECT), "geo.c"); curr->index = prim_obj_cnt; curr->next = NULL; strcpy(curr->name, objname); if (gm->modelroot == NULL) gm->modelroot = curr; else prev->next = curr; /* Get surface characteristics. */ ps = GlobalMalloc(sizeof(SURF), "geo.c"); curr->surf = ps; stat = fscanf(pf, "%lf %lf %lf %lf %lf %lf", &(ps->fcolor[0]), &(ps->fcolor[1]), &(ps->fcolor[2]), &(ps->bcolor[0]), &(ps->bcolor[1]), &(ps->bcolor[2])); if (stat != 6) { printf("Object color incorrect.\n"); exit(-1); } stat = fscanf(pf, "%lf %lf %lf %lf %lf", &(ps->kdiff), &(ps->kspec), &(ps->ktran), &(ps->refrindex), &(ps->kspecn)); if (stat != 5) { printf("Object surface coefficients incorrect.\n"); exit(-1); } /* Get texture and flag information. */ stat = fscanf(pf, "%ld %ld %ld %ld\n", &dummy, &dummy, &dummy, &dummy); if (stat != 4) { printf("Texture and/or flag information not all present.\n"); exit(-1); } /* Get primitive opcode. */ stat = fscanf(pf, "%c %ld", &primop, &(curr->numelements)); if (stat != 2) { printf("Object primitive opcode.\n"); exit(-1); } switch (primop) { case 's': curr->procs = &SphProcs; break; case 'p': curr->procs = &PolyProcs; break; case 't': curr->procs = &TriProcs; break; case 'c': case 'q': printf("Code for cylinders and quadrics not implemented yet.\n"); exit(-1); default: printf("Invalid primitive type \'%c\'.\n", primop); exit(-1); } /* Allocate primitive elements and create indices. */ pe = GlobalMalloc(sizeof(ELEMENT)*curr->numelements, "geo.c"); curr->pelem = pe; prim_elem_cnt += curr->numelements; for (i = 1; i <= curr->numelements; i++, pe++) pe->index = i; /* Read, transform, and compute bounding box for object. */ (*curr->procs->read)(curr, pf); (*curr->procs->transform)(curr, model, modelInvT); (*curr->procs->bbox)(curr); prev = curr; } NormalizeGeo(gm->modelroot, model, modelInvT); fclose(pf); }
VOID *ObjectMalloc(INT ObjectType, INT count) { INT n; VOID *p; switch (ObjectType) { case OT_GRID: n = count*sizeof(GRID); p = GlobalMalloc(n, "GRID"); mem_grid += n; maxmem_grid = Max(mem_grid, maxmem_grid); break; case OT_VOXEL: n = count*sizeof(VOXEL); p = GlobalMalloc(n, "VOXEL"); mem_voxel += n; maxmem_voxel = Max(mem_voxel, maxmem_voxel); break; case OT_HASHTABLE: { INT i; VOXEL **x; n = count*sizeof(VOXEL *); p = GlobalMalloc(n, "HASHTABLE"); x = p; for (i = 0; i < count; i++) x[i] = NULL; mem_hashtable += n; maxmem_hashtable = Max(mem_hashtable, maxmem_hashtable); } break; case OT_EMPTYCELLS: { INT i, w; UINT *x; w = 1 + count/(8*sizeof(UINT)); n = w*sizeof(UINT); p = GlobalMalloc(n, "EMPTYCELLS"); x = p; for (i = 0; i < w; i++) x[i] = ~0; /* 1 => empty */ mem_emptycells += n; maxmem_emptycells = Max(mem_emptycells, maxmem_emptycells); } break; case OT_BINTREE: n = count*sizeof(BTNODE); p = GlobalMalloc(n, "BINTREE"); mem_bintree += n; maxmem_bintree = Max(mem_bintree, maxmem_bintree); break; case OT_PEPARRAY: n = count*sizeof(ELEMENT *); p = GlobalMalloc(n, "PEPARRAY"); mem_pepArray += n; maxmem_pepArray = Max(mem_pepArray, maxmem_pepArray); break; default: printf("ObjectMalloc: Unknown object type: %ld\n", ObjectType); exit(-1); } return (p); }
VOID *GlobalRealloc(VOID *p, UINT size) { UINT oldsize; UINT newsize; UINT totsize; VOID huge *q; UINT huge *r; UINT huge *s; NODE huge *pn; NODE huge *prev; NODE huge *curr; NODE huge *next; NODE huge *node; if (!size) { GlobalFree(p); return (NULL); } if (!p) return (GlobalMalloc(size, "GlobalRealloc")); pn = NODE_ADD(p, -nodesize); /* Adjust ptr back to arena. */ if (pn->cksm != CKSM) { fprintf(stderr, "GlobalRealloc: Attempted to realloc node with invalid checksum.\n"); exit(1); } if (pn->free) { fprintf(stderr, "GlobalRealloc: Attempted to realloc an unallocated node.\n"); exit(1); } newsize = ROUND_UP(size); oldsize = pn->size; /* * If new size is less than current node size, truncate the node * and return end to free list. */ if (newsize <= oldsize) { if (oldsize - newsize < THRESHOLD) return (p); pn->size = newsize; next = NODE_ADD(p, newsize); next->size = oldsize - nodesize - newsize; next->next = NULL; next->free = FALSE; next->cksm = CKSM; next = NODE_ADD(next, nodesize); GlobalFree(next); return (p); } /* * New size is bigger than current node. Try to expand next node * in list. */ next = NODE_ADD(p, oldsize); totsize = oldsize + nodesize + next->size; { pthread_mutex_lock(&(gm->memlock)); } if (next < endmem && next->free && totsize >= newsize) { /* Find next in free list. */ prev = NULL; curr = gm->freelist; while (curr && curr < next && curr < endmem) { prev = curr; curr = curr->next; } if (curr != next) { fprintf(stderr, "GlobalRealloc: Could not find next node in free list.\n"); exit(1); } if (totsize - newsize < THRESHOLD) { /* Just remove next from free list. */ if (!prev) gm->freelist = next->next; else prev->next = next->next; next->next = NULL; next->free = FALSE; pn->size = totsize; { pthread_mutex_unlock(&(gm->memlock)); } return (p); } else { /* Remove next from free list while adding node. */ node = NODE_ADD(p, newsize); node->next = next->next; node->size = totsize - nodesize - newsize; node->free = TRUE; node->cksm = CKSM; if (!prev) gm->freelist = node; else prev->next = node; next->next = NULL; next->free = FALSE; pn->size = newsize; { pthread_mutex_unlock(&(gm->memlock)); } return (p); } } /* * New size is bigger than current node, but next node in list * could not be expanded. Try to allocate new node and move data * to new location. */ { pthread_mutex_unlock(&(gm->memlock)); } s = q = GlobalMalloc(newsize, "GlobalRealloc"); if (!q) return (NULL); r = (UINT huge *)p; oldsize >>= 2; while (oldsize--) *s++ = *r++; GlobalFree(p); return (q); }