static int do_allocate(vm_map_t map, void **addr, size_t size, int anywhere) { struct region *reg; char *start, *end, *phys; if (size == 0) return EINVAL; /* * Allocate region */ if (anywhere) { size = (size_t)PAGE_ALIGN(size); if ((reg = region_alloc(&map->head, size)) == NULL) return ENOMEM; } else { start = (char *)PAGE_TRUNC(*addr); end = (char *)PAGE_ALIGN(start + size); size = (size_t)(end - start); reg = region_find(&map->head, start, size); if (reg == NULL || !(reg->flags & REG_FREE)) return EINVAL; reg = region_split(&map->head, reg, start, size); if (reg == NULL) return ENOMEM; } reg->flags = REG_READ | REG_WRITE; /* * Allocate physical pages, and map them into virtual address */ if ((phys = page_alloc(size)) == 0) goto err1; if (mmu_map(map->pgd, phys, reg->addr, size, PG_WRITE)) goto err2; reg->phys = phys; /* Zero fill */ memset(phys_to_virt(phys), 0, reg->size); *addr = reg->addr; return 0; err2: page_free(phys, size); err1: region_free(&map->head, reg); return ENOMEM; }
void zw::geoData::subdivide( geo_ptr &data, cell_size_t &extant ) { auto created = extant; // Store Links To Future-Nodes std::vector<deferral> deferred; for ( cell_size_t parent = 0; parent < extant; ++parent ) { for ( int spoke = 0; spoke < 6; ++spoke ) { auto child = data[parent].link[spoke]; if ( child >= extant ) continue; // we already split this pair // Create new node at the modpoint of pair for ( int s = 0; s < 6; ++s ) data[created].link[s] = nolink - 1; data[created].v = ( data[parent].v + data[child].v ) / 2; data[created].v.normalize(); data[created].region = ( created < REGION_LIMIT ) ? created : region_split( data[parent].region, data[child].region ); region_score[data[created].region] += 1; // // Here's how the linking works. In the original hexagon, there is // a "center" which is the parent node. This center has 6 spokes // leading to the vertices of the hexagon. We are creating a new // point between the parent and one of the spokes -- the child. The // created node needs to be linked to both the parent and child. In // the original hexagon, we also need to know the child's sibling // nodes on either side from the parent - counter-clockwise and // clockwise. // // During this iteration, the links between these two nodes and both // the parent and child should be subdivided just like this spoke, // creating four new nodes. Our newly created node needs to link to // all four of these. Some of them are likely to have already been // created previously in the subdivision process and we can link // straight to them. Others will not have been created yet and we'll // need to set up deferred links which will be created when the // nodes are. // // link[0] = parent // link[1] = new node between parent and counter-clockwise sibling // link[2] = new node between counter-clockwise sibling and child // link[3] = child // link[4] = new node between clockwise sibling and child // link[5] = new node between parent and clockwise sibling // // Link To Parent data[created].link[0] = parent; data[parent].link[spoke] = created; // Link To Counter-Clockwise Siblings auto neighbor = data[parent].prevNeighbor( spoke ); if ( neighbor >= extant ) { data[created].link[1] = neighbor; if ( data[neighbor].link[0] == parent ) neighbor = data[neighbor].link[3]; else neighbor = data[neighbor].link[0]; } else deferred.push_back( deferral( parent, neighbor, 1, created ) ); for ( int s = 0; s < 6; ++s ) { if ( data[neighbor].link[s] == child ) { deferred.push_back( deferral( child, neighbor, 2, created ) ); break; } else if ( ( data[data[neighbor].link[s]].link[0] == child && data[data[neighbor].link[s]].link[3] == neighbor ) || ( data[data[neighbor].link[s]].link[0] == neighbor && data[data[neighbor].link[s]].link[3] == child ) ) { data[created].link[2] = data[neighbor].link[s]; break; } } // Link To Child data[created].link[3] = child; for ( int s = 0; s < 6; ++s ) { if ( data[child].link[s] == parent ) { data[child].link[s] = created; break; } } // Link To Clockwise Siblings neighbor = data[parent].nextNeighbor( spoke ); if ( neighbor >= extant ) { data[created].link[5] = neighbor; if ( data[neighbor].link[0] == parent ) neighbor = data[neighbor].link[3]; else neighbor = data[neighbor].link[0]; } else deferred.push_back( deferral( parent, neighbor, 5, created ) ); for ( int s = 0; s < 6; ++s ) { if ( data[neighbor].link[s] == child ) { deferred.push_back( deferral( child, neighbor, 4, created ) ); break; } else if ( ( data[data[neighbor].link[s]].link[0] == child && data[data[neighbor].link[s]].link[3] == neighbor ) || ( data[data[neighbor].link[s]].link[0] == neighbor && data[data[neighbor].link[s]].link[3] == child ) ) { data[created].link[4] = data[neighbor].link[s]; break; } } // We have finished creating this node. ++created; } } for ( auto const &d : deferred ) { for ( int s = 0; s < 6; ++s ) { auto other = data[d.a].link[s]; if ( ( data[other].link[0] == d.a && data[other].link[3] == d.b ) || ( data[other].link[3] == d.a && data[other].link[0] == d.b ) ) { data[d.t].link[d.s] = other; break; } assert( s != 5 ); // we should never get here } } // We're Done extant = created; }