void f_free(void * ptr) { struct f_malloc_block * blk; /* stats */ if (!ptr) { return; } blk = (struct f_malloc_block *)((uint8_t *)ptr - sizeof(struct f_malloc_block)); if (blk->magic == F_MALLOC_MAGIC) { blk->flags = 0u; /* stats */ f_malloc_stats[blk->flags & MEM_USER].free_calls++; f_malloc_stats[blk->flags & MEM_USER].objects_allocated--; f_malloc_stats[blk->flags & MEM_USER].mem_allocated -= (uint32_t)blk->size; /* Merge adjecent free blocks */ //XXX: How to check if actually adjacent? -> Pointer arithmetic? (sizeof(struct) + blk->size) ? // Or just assume for now that they are adjacent? -> Like FreeRTOS heap4 if ((blk->prev) && (!in_use(blk->prev))) { blk = merge_blocks(blk->prev, blk); } if ((blk->next) && (!in_use(blk->next))) { blk = merge_blocks(blk, blk->next); } } else { dbg_malloc("FREE ERR: %p is not a valid allocated pointer!\n", blk); } }
/* free block */ void my_free(void *ptr) { Meminfo *temp = meminfo; Meminfo *prev = NULL; if(ptr==NULL) { log_D("NULL address cannot be free"); return ; } while(temp) { if((void *)(temp+1)==ptr) { temp->is_free = TRUE; log_D("Given address is valid and marked as free"); /* Combine next free space */ if(temp->next!=NULL && temp->next->is_free==TRUE) { merge_blocks(temp); } /* combine this space with previous one if free*/ if(prev!=NULL && prev->is_free==TRUE) { merge_blocks(prev); } return; } prev = temp; temp = temp->next; } log_D("Given address is invalid for freeing"); }
inline void merge_sort_by_key_on_cpu(KeyIterator keys_first, KeyIterator keys_last, ValueIterator values_first, Compare compare, command_queue &queue) { typedef typename std::iterator_traits<KeyIterator>::value_type key_type; typedef typename std::iterator_traits<ValueIterator>::value_type value_type; size_t count = iterator_range_size(keys_first, keys_last); if(count < 2){ return; } // for small input size only insertion sort is performed else if(count <= 512){ block_insertion_sort(keys_first, values_first, compare, count, count, true, queue); return; } const context &context = queue.get_context(); const device &device = queue.get_device(); // loading parameters std::string cache_key = std::string("__boost_merge_sort_by_key_on_cpu_") + type_name<value_type>() + "_with_" + type_name<key_type>(); boost::shared_ptr<parameter_cache> parameters = detail::parameter_cache::get_global_cache(device); const size_t block_size = parameters->get(cache_key, "insertion_sort_by_key_block_size", 64); block_insertion_sort(keys_first, values_first, compare, count, block_size, true, queue); // temporary buffer for merge results vector<value_type> values_temp(count, context); vector<key_type> keys_temp(count, context); bool result_in_temporary_buffer = false; for(size_t i = block_size; i < count; i *= 2){ result_in_temporary_buffer = !result_in_temporary_buffer; if(result_in_temporary_buffer) { merge_blocks(keys_first, values_first, keys_temp.begin(), values_temp.begin(), compare, count, i, true, queue); } else { merge_blocks(keys_temp.begin(), values_temp.begin(), keys_first, values_first, compare, count, i, true, queue); } } if(result_in_temporary_buffer) { copy(keys_temp.begin(), keys_temp.end(), keys_first, queue); copy(values_temp.begin(), values_temp.end(), values_first, queue); } }
inline void dispatch_merge_blocks(Iterator first, Iterator result, Compare compare, size_t count, const size_t block_size, const size_t input_size_threshold, const size_t blocks_no_threshold, command_queue &queue) { const size_t blocks_no = static_cast<size_t>( std::ceil(float(count) / block_size) ); // merge with merge path should used only for the large arrays and at the // end of merging part when there are only a few big blocks left to be merged if(blocks_no <= blocks_no_threshold && count >= input_size_threshold){ Iterator last = first + count; for(size_t i = 0; i < count; i+= 2*block_size) { Iterator first1 = (std::min)(first + i, last); Iterator last1 = (std::min)(first1 + block_size, last); Iterator first2 = last1; Iterator last2 = (std::min)(first2 + block_size, last); Iterator block_result = (std::min)(result + i, result + count); merge_with_merge_path(first1, last1, first2, last2, block_result, compare, queue); } } else { merge_blocks(first, result, compare, count, block_size, false, queue); } }
extern bool coalesce_headers() { Header* larger, *smaller; bool merged = false; int i; // Only loop to 31 because loop accesses i+1 for (i = 0; i < 31; i++) { smaller = freelist[i][0]; larger = freelist[i+1][0]; while (larger != NULL) { while (smaller != NULL) { // If the blocks are back to back if (((long) larger + sizeof(Header) + get_free_size(larger)) == (long) smaller) { assert(!larger->is_allocated && !smaller->is_allocated); // Blocks are buddies, merge them merge_blocks(larger, smaller); merged = true; } smaller = smaller->next_header; } smaller = freelist[i][0]; larger = larger->next_header; } } return merged; }
inline void merge_blocks(Iterator first, Iterator result, Compare compare, size_t count, const size_t block_size, const bool sort_by_key, command_queue &queue) { // dummy iterator as it's not sort by key Iterator dummy; merge_blocks(first, dummy, result, dummy, compare, count, block_size, false, queue); }
void sort2() { #pragma omp parallel for for (int i = 0; i < N; i += group_size) { qsort((void*)(array+i), end(i)-start(i), sizeof(int), cmpfunc); } for (int i = 0; i < N; i++) { #pragma omp parallel for for (int j = i%2; j < GROUPS; j++) { merge_blocks(j); } } }
int free_some_memory(void *pointer_to_free) { int freed_memory_entry = find_memory_pointer(pointer_to_free); mem_entry *cur_entry; if (freed_memory_entry==-1) return (0); cur_entry = &mem_array[freed_memory_entry]; if (cur_entry->empty) return (1); cur_entry->task_id = -1; cur_entry->empty = 1; cur_entry->kept_open = 0; strcpy(cur_entry->allocby,"EMPTY"); merge_blocks(freed_memory_entry); return (1); }
void kfree(void *p) { block_info *b; if(p == NULL) { return; } /* Retrieve the block info pointer */ b = p; b--; /* Mark block as free */ b->state = STATE_FREE; /* Merge free blocks */ merge_blocks(); }
int gmx_make_ndx(int argc, char *argv[]) { const char *desc[] = { "Index groups are necessary for almost every GROMACS program.", "All these programs can generate default index groups. You ONLY", "have to use [THISMODULE] when you need SPECIAL index groups.", "There is a default index group for the whole system, 9 default", "index groups for proteins, and a default index group", "is generated for every other residue name.[PAR]", "When no index file is supplied, also [THISMODULE] will generate the", "default groups.", "With the index editor you can select on atom, residue and chain names", "and numbers.", "When a run input file is supplied you can also select on atom type.", "You can use NOT, AND and OR, you can split groups", "into chains, residues or atoms. You can delete and rename groups.[PAR]", "The atom numbering in the editor and the index file starts at 1.[PAR]", "The [TT]-twin[tt] switch duplicates all index groups with an offset of", "[TT]-natoms[tt], which is useful for Computational Electrophysiology", "double-layer membrane setups." }; static int natoms = 0; static gmx_bool bVerbose = FALSE; static gmx_bool bDuplicate = FALSE; t_pargs pa[] = { { "-natoms", FALSE, etINT, {&natoms}, "set number of atoms (default: read from coordinate or index file)" }, { "-twin", FALSE, etBOOL, {&bDuplicate}, "Duplicate all index groups with an offset of -natoms" }, { "-verbose", FALSE, etBOOL, {&bVerbose}, "HIDDENVerbose output" } }; #define NPA asize(pa) output_env_t oenv; char title[STRLEN]; int nndxin; const char *stxfile; char **ndxinfiles; const char *ndxoutfile; gmx_bool bNatoms; int i, j; t_atoms *atoms; rvec *x, *v; int ePBC; matrix box; t_blocka *block, *block2; char **gnames, **gnames2; t_filenm fnm[] = { { efSTX, "-f", NULL, ffOPTRD }, { efNDX, "-n", NULL, ffOPTRDMULT }, { efNDX, "-o", NULL, ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, 0, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } stxfile = ftp2fn_null(efSTX, NFILE, fnm); if (opt2bSet("-n", NFILE, fnm)) { nndxin = opt2fns(&ndxinfiles, "-n", NFILE, fnm); } else { nndxin = 0; } ndxoutfile = opt2fn("-o", NFILE, fnm); bNatoms = opt2parg_bSet("-natoms", NPA, pa); if (!stxfile && !nndxin) { gmx_fatal(FARGS, "No input files (structure or index)"); } if (stxfile) { snew(atoms, 1); get_stx_coordnum(stxfile, &(atoms->nr)); init_t_atoms(atoms, atoms->nr, TRUE); snew(x, atoms->nr); snew(v, atoms->nr); fprintf(stderr, "\nReading structure file\n"); read_stx_conf(stxfile, title, atoms, x, v, &ePBC, box); natoms = atoms->nr; bNatoms = TRUE; } else { atoms = NULL; x = NULL; } /* read input file(s) */ block = new_blocka(); gnames = NULL; printf("Going to read %d old index file(s)\n", nndxin); if (nndxin) { for (i = 0; i < nndxin; i++) { block2 = init_index(ndxinfiles[i], &gnames2); srenew(gnames, block->nr+block2->nr); for (j = 0; j < block2->nr; j++) { gnames[block->nr+j] = gnames2[j]; } sfree(gnames2); merge_blocks(block, block2); sfree(block2->a); sfree(block2->index); /* done_block(block2); */ sfree(block2); } } else { snew(gnames, 1); analyse(atoms, block, &gnames, FALSE, TRUE); } if (!bNatoms) { natoms = block2natoms(block); printf("Counted atom numbers up to %d in index file\n", natoms); } edit_index(natoms, atoms, x, block, &gnames, bVerbose); write_index(ndxoutfile, block, gnames, bDuplicate, natoms); return 0; }
static code_block *generate_do_while(code_block *parent, loop_statement *loop) { size_t body_block = parent->system->block_count; code_block *body = fork_block(parent), *context = body; if (loop->body) { struct generate_loop_trigger_data data = { .loop = loop, .done = false, .prev_block = body, .context_block = &context }; body = generate_block(body, loop->body, loop_trigger, &data); } // if the body ends, it implicitly continues if (body) { block_node *node = xmalloc(sizeof(*node)); node->block = body; node->next = loop->continue_node; loop->continue_node = node; } // if we ever continue the loop, we'll want to include the available variables // these variables: // - need to be in the outermost scope in the loop // - need to be available from all continue statements (including the final // implicit continue) if (loop->continue_node) { code_block *condition = tangle_blocks(context, loop->continue_node); condition = generate_expression(condition, loop->condition); code_block *body_replay, *post; weave_blocks(parent, loop->break_node, condition, &body_replay, &post); join_blocks(body_replay, body_block); return post; } // loop only breaks, never continues (effectively not a loop) if (loop->break_node) { fprintf(stderr, "do-while condition not reachable\n"); return tangle_blocks(parent, loop->break_node); } fprintf(stderr, "infinite loop, do-while condition not reachable\n"); return NULL; } static code_block *generate_while(code_block *parent, loop_statement *loop) { if (loop->condition->operation.type == O_LITERAL && loop->condition->type->type == T_BOOL && loop->condition->value_bool) { loop->type = S_DO_WHILE; return generate_do_while(parent, loop); } size_t condition_block = parent->system->block_count; code_block *condition = fork_block(parent); condition = generate_expression(condition, loop->condition); code_block *body, *post; branch_into(condition, &body, &post); // TODO: this is using undocumented behavior size_t /*body_block = parent->system->block_count - 2, */post_block = parent->system->block_count - 1; loop->condition_block = condition_block; loop->post_block = post_block; if (loop->body) { body = generate_block(body, loop->body, NULL, NULL); } if (body) { join_blocks(body, condition_block); } return post; } static code_block *generate_loop(code_block *parent, loop_statement *loop) { return loop->type == S_DO_WHILE ? generate_do_while(parent, loop) : generate_while(parent, loop); } static code_block *generate_if(code_block *parent, if_statement *branch) { parent = generate_expression(parent, branch->condition); code_block *first, *second; branch_into(parent, &first, &second); first = branch->first ? generate_block(first, branch->first, NULL, NULL) : first; second = branch->second ? generate_block(second, branch->second, NULL, NULL) : second; switch (((!first) << 1) | (!second)) { case 0: // both exist return merge_blocks(parent, first, second); case 1: // the first block exists return rejoin_block(parent, first); case 2: // the second block exists return rejoin_block(parent, second); case 3: return NULL; } fprintf(stderr, "if statement generation logical failure\n"); abort(); }
int gmx_make_ndx(int argc, char *argv[]) { const char *desc[] = { "Index groups are necessary for almost every GROMACS program.", "All these programs can generate default index groups. You ONLY", "have to use [THISMODULE] when you need SPECIAL index groups.", "There is a default index group for the whole system, 9 default", "index groups for proteins, and a default index group", "is generated for every other residue name.", "", "When no index file is supplied, also [THISMODULE] will generate the", "default groups.", "With the index editor you can select on atom, residue and chain names", "and numbers.", "When a run input file is supplied you can also select on atom type.", "You can use boolean operations, you can split groups", "into chains, residues or atoms. You can delete and rename groups.", "Type 'h' in the editor for more details.", "", "The atom numbering in the editor and the index file starts at 1.", "", "The [TT]-twin[tt] switch duplicates all index groups with an offset of", "[TT]-natoms[tt], which is useful for Computational Electrophysiology", "double-layer membrane setups.", "", "See also [gmx-select] [TT]-on[tt], which provides an alternative way", "for constructing index groups. It covers nearly all of [THISMODULE]", "functionality, and in many cases much more." }; static int natoms = 0; static gmx_bool bVerbose = FALSE; static gmx_bool bDuplicate = FALSE; t_pargs pa[] = { { "-natoms", FALSE, etINT, {&natoms}, "set number of atoms (default: read from coordinate or index file)" }, { "-twin", FALSE, etBOOL, {&bDuplicate}, "Duplicate all index groups with an offset of -natoms" }, { "-verbose", FALSE, etBOOL, {&bVerbose}, "HIDDENVerbose output" } }; #define NPA asize(pa) gmx_output_env_t *oenv; const char *stxfile; const char *ndxoutfile; gmx_bool bNatoms; int j; t_atoms *atoms; rvec *x, *v; int ePBC; matrix box; t_blocka *block, *block2; char **gnames, **gnames2; t_filenm fnm[] = { { efSTX, "-f", nullptr, ffOPTRD }, { efNDX, "-n", nullptr, ffOPTRDMULT }, { efNDX, "-o", nullptr, ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, 0, NFILE, fnm, NPA, pa, asize(desc), desc, 0, nullptr, &oenv)) { return 0; } stxfile = ftp2fn_null(efSTX, NFILE, fnm); gmx::ArrayRef<const std::string> ndxInFiles = opt2fnsIfOptionSet("-n", NFILE, fnm); ndxoutfile = opt2fn("-o", NFILE, fnm); bNatoms = opt2parg_bSet("-natoms", NPA, pa); if (!stxfile && ndxInFiles.empty()) { gmx_fatal(FARGS, "No input files (structure or index)"); } if (stxfile) { t_topology *top; snew(top, 1); fprintf(stderr, "\nReading structure file\n"); read_tps_conf(stxfile, top, &ePBC, &x, &v, box, FALSE); atoms = &top->atoms; if (atoms->pdbinfo == nullptr) { snew(atoms->pdbinfo, atoms->nr); } natoms = atoms->nr; bNatoms = TRUE; } else { atoms = nullptr; x = nullptr; } /* read input file(s) */ block = new_blocka(); gnames = nullptr; printf("Going to read %td old index file(s)\n", ndxInFiles.size()); if (!ndxInFiles.empty()) { for (const std::string &ndxInFile : ndxInFiles) { block2 = init_index(ndxInFile.c_str(), &gnames2); srenew(gnames, block->nr+block2->nr); for (j = 0; j < block2->nr; j++) { gnames[block->nr+j] = gnames2[j]; } sfree(gnames2); merge_blocks(block, block2); sfree(block2->a); sfree(block2->index); /* done_block(block2); */ sfree(block2); } } else { snew(gnames, 1); analyse(atoms, block, &gnames, FALSE, TRUE); } if (!bNatoms) { natoms = block2natoms(block); printf("Counted atom numbers up to %d in index file\n", natoms); } edit_index(natoms, atoms, x, block, &gnames, bVerbose); write_index(ndxoutfile, block, gnames, bDuplicate, natoms); return 0; }
int transpose_inplace( float *a, // matrix to transpose (row-major order) long nrows, // number of rows in matrix a long ncols, // number of columns in matrix a const struct Transpose_Progress_Callback *progress // optional callback functor for status; NULL for none ) // Transposes matrix of nrows x ncols elements to ncols x nrows. // Returns 0 on success, 1 if a memory allocation error occurred (with matrix unchanged), // or -1 if canceled via progress callback (leaving matrix corrupted). { int error; int cancel = 0; void *bufin = NULL; void *bufout = NULL; Band_Info *RESTRICT pinfo = NULL; Band_Info *RESTRICT qinfo = NULL; struct Transpose_Progress_Info progress_info; struct Transpose_Progress_Info *progress_ptr = NULL; int nbands = choose_bands_inplace( nrows, ncols ); if (nbands == 0) { return 0; // no work to do (nrows <= 1 or ncols <= 1) } if (nbands <= 2) { return transpose_inplace_small( a, nrows, ncols ); } error = setup_bands( a, a, nrows, ncols, nbands, nbands, &bufin, &bufout, &pinfo, &qinfo ); if (error) { return 1; } if (progress) { progress_info.progress = progress; progress_info.per_move = 2.0 / (float)( 7 * (LONG)nbands * (LONG)nbands - (LONG)nbands ); progress_info.moves_done = 0; progress_ptr = &progress_info; } cancel = cancel || isolate_blocks( a, pinfo, qinfo, nrows, ncols, nbands, progress_ptr ); cancel = cancel || transpose_blocks( pinfo, qinfo, nbands, progress_ptr ); free( bufin ); // pinfo[nbands-1].addr = NULL; cancel = cancel || merge_blocks( a, pinfo, qinfo, nrows, ncols, nbands, progress_ptr ); free( bufout ); free( pinfo ); free( qinfo ); if (cancel) { return -1; } return 0; }