int main() { TItem *list = malloc(sizeof(TItem)); *list = malloc(sizeof(TItem)); *((TItem *) *list) = NULL; dispose_list(&list); dispose_list(&list); return 0; }
static int free_inodes(int goal) { struct list_head *tmp, *head = &inode_in_use; LIST_HEAD(freeable); int found = 0, depth = goal << 1; while ((tmp = head->prev) != head && depth--) { struct inode * inode = list_entry(tmp, struct inode, i_list); list_del(tmp); if (CAN_UNUSE(inode)) { list_del(&inode->i_hash); INIT_LIST_HEAD(&inode->i_hash); list_add(tmp, &freeable); if (++found < goal) continue; break; } list_add(tmp, head); } if (found) { spin_unlock(&inode_lock); dispose_list(&freeable); spin_lock(&inode_lock); } return found; }
static int free_inodes(void) { struct list_head list, *entry, *freeable = &list; int found = 0; INIT_LIST_HEAD(freeable); entry = inode_in_use.next; while (entry != &inode_in_use) { struct list_head *tmp = entry; entry = entry->next; if (!CAN_UNUSE(INODE(tmp))) continue; list_del(tmp); list_del(&INODE(tmp)->i_hash); INIT_LIST_HEAD(&INODE(tmp)->i_hash); list_add(tmp, freeable); list_entry(tmp, struct inode, i_list)->i_state = I_FREEING; found = 1; } if (found) dispose_list(freeable); return found; }
/* * This is a two-stage process. First we collect all * offending inodes onto the throw-away list, and in * the second stage we actually dispose of them. This * is because we don't want to sleep while messing * with the global lists.. */ int invalidate_inodes(struct super_block * sb) { int busy; LIST_HEAD(throw_away); spin_lock(&inode_lock); busy = invalidate_list(&inode_in_use, sb, &throw_away); busy |= invalidate_list(&sb->s_dirty, sb, &throw_away); dispose_list(&throw_away); spin_unlock(&inode_lock); return busy; }
/* Adds memory dependencies based on ordering type: 0 - exact; 1 - strong; 2 - weak; 3 - none */ void add_memory_dep (cuc_func *f, int otype) { int b, i; dep_list *all_mem = NULL; for (b = 0; b < f->num_bb; b++) { cuc_insn *insn = f->bb[b].insn; for (i = 0; i < f->bb[b].ninsn; i++) if (insn[i].type & IT_MEMORY) { dep_list *tmp = all_mem; while (tmp) { //PRINTF ("%x %x\n", REF (b,i), tmp->ref); if (check_memory_conflict (f, &insn[i], &f->INSN(tmp->ref), otype)) add_dep (&insn[i].dep, tmp->ref); tmp = tmp->next; } add_dep (&all_mem, REF (b, i)); } } dispose_list (&all_mem); }
static w_query_expr *parse_list(w_query *query, json_t *term, bool allof) { struct w_expr_list *list; size_t i; /* don't allow "allof" on its own */ if (!json_is_array(term) || json_array_size(term) < 2) { query->errmsg = strdup("must use [\"allof\", expr...]"); return NULL; } list = calloc(1, sizeof(*list)); if (!list) { query->errmsg = strdup("out of memory"); return NULL; } list->allof = allof; list->num = json_array_size(term) - 1; list->exprs = calloc(list->num, sizeof(list->exprs[0])); for (i = 0; i < list->num; i++) { w_query_expr *parsed; json_t *exp = json_array_get(term, i + 1); parsed = w_query_expr_parse(query, exp); if (!parsed) { // other expression parser sets errmsg dispose_list(list); return NULL; } list->exprs[i] = parsed; } return w_query_expr_new(eval_list, dispose_list, list); }
/* Schedule memory accesses 0 - exact; 1 - strong; 2 - weak; 3 - none */ int schedule_memory (cuc_func *f, int otype) { int b, i, j; int modified = 0; f->nmsched = 0; for (b = 0; b < f->num_bb; b++) { cuc_insn *insn = f->bb[b].insn; for (i = 0; i < f->bb[b].ninsn; i++) if (insn[i].type & IT_MEMORY) { f->msched[f->nmsched++] = REF (b, i); if (otype == MO_NONE || otype == MO_WEAK) insn[i].type |= IT_FLAG1; /* mark unscheduled */ } } for (i = 0; i < f->nmsched; i++) cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' '); cucdebug (2, "\n"); /* We can reorder just more loose types We assume, that memory accesses are currently in valid (but not neccesserly) optimal order */ if (otype == MO_WEAK || otype == MO_NONE) { for (i = 0; i < f->nmsched; i++) { int best = i; int tmp; for (j = i + 1; j < f->nmsched; j++) if (REF_BB(f->msched[j]) == REF_BB(f->msched[best])) { if (mem_ordering_cmp (f, &f->INSN (f->msched[j]), &f->INSN(f->msched[best]))) { /* Check dependencies */ dep_list *t = f->INSN(f->msched[j]).dep; while (t) { if (f->INSN(t->ref).type & IT_FLAG1) break; t = t->next; } if (!t) best = j; /* no conflicts -> ok */ } } /* we have to shift instructions up, to maintain valid dependencies and make space for best candidate */ /* make local copy */ tmp = f->msched[best]; for (j = best; j > i; j--) f->msched[j] = f->msched[j - 1]; f->msched[i] = tmp; f->INSN(f->msched[i]).type &= ~IT_FLAG1; /* mark scheduled */ } } for (i = 0; i < f->nmsched; i++) cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' '); cucdebug (2, "\n"); /* Assign memory types */ for (i = 0; i < f->nmsched; i++) { cuc_insn *a = &f->INSN(f->msched[i]); f->mtype[i] = !II_IS_LOAD(a->index) ? MT_STORE : MT_LOAD; f->mtype[i] |= II_MEM_WIDTH (a->index); if (a->type & IT_SIGNED) f->mtype[i] |= MT_SIGNED; } if (same_transfers (f, otype)) modified = 1; if (join_transfers (f, otype)) modified = 1; for (i = 0; i < f->nmsched; i++) cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' '); cucdebug (2, "\n"); if (cuc_debug > 5) print_cuc_bb (f, "AFTER_MEM_REMOVAL"); if (config.cuc.enable_bursts) { //PRINTF ("\n"); for (i = 1; i < f->nmsched; i++) { cuc_insn *a = &f->INSN(f->msched[i - 1]); cuc_insn *b = &f->INSN(f->msched[i]); int aw = f->mtype[i - 1] & MT_WIDTH; /* Burst can only be out of words */ if (aw != 4) continue; if ((a->opt[1] & OPT_REF) && f->INSN(a->op[1]).index == II_ADD &&(b->opt[1] & OPT_REF) && f->INSN(b->op[1]).index == II_ADD) { a = &f->INSN(a->op[1]); b = &f->INSN(b->op[1]); /* Not in usual form? */ if (a->opt[1] != b->opt[1] || a->op[1] != b->op[1] || a->opt[2] != OPT_CONST || b->opt[2] != OPT_CONST) continue; //PRINTF ("%i %i, ", a->op[2], b->op[2]); /* Check if they touch together */ if (a->op[2] + aw == b->op[2] && REF_BB(f->msched[i - 1]) == REF_BB(f->msched[i])) { /* yes => do burst */ f->mtype[i - 1] &= ~MT_BURSTE; f->mtype[i - 1] |= MT_BURST; f->mtype[i] |= MT_BURST | MT_BURSTE; } } } } for (i = 0; i < f->nmsched; i++) cucdebug (2, "[%x]%x%c ", f->msched[i], f->mtype[i] & MT_WIDTH, (f->mtype[i] & MT_BURST) ? (f->mtype[i] & MT_BURSTE) ? 'E' : 'B' : ' '); cucdebug (2, "\n"); /* We don't need dependencies in non-memory instructions */ for (b = 0; b < f->num_bb; b++) { cuc_insn *insn = f->bb[b].insn; for (i = 0; i < f->bb[b].ninsn; i++) if (!(insn[i].type & IT_MEMORY)) dispose_list (&insn[i].dep); } if (cuc_debug > 5) print_cuc_bb (f, "AFTER_MEM_REMOVAL2"); /* Reduce number of dependecies, keeping just direct dependencies, based on memory schedule */ { int lastl[3] = {-1, -1, -1}; int lasts[3] = {-1, -1, -1}; int lastc[3] = {-1, -1, -1}; int last_load = -1, last_store = -1, last_call = -1; for (i = 0; i < f->nmsched; i++) { int t = f->mtype[i] & MT_LOAD ? 0 : f->mtype[i] & MT_STORE ? 1 : 2; int maxl = lastl[t]; int maxs = lasts[t]; int maxc = lastc[t]; dep_list *tmp = f->INSN(f->msched[i]).dep; cucdebug (7, "!%i %x %p\n", i, f->msched[i], tmp); while (tmp) { if (f->INSN(tmp->ref).type & IT_MEMORY && REF_BB(tmp->ref) == REF_BB(f->msched[i])) { cucdebug (7, "%i %x %lx\n", i, f->msched[i], tmp->ref); /* Search for the reference */ for (j = 0; j < f->nmsched; j++) if (f->msched[j] == tmp->ref) break; assert (j < f->nmsched); if (f->mtype[j] & MT_STORE) { if (maxs < j) maxs = j; } else if (f->mtype[j] & MT_LOAD) { if (maxl < j) maxl = j; } else if (f->mtype[j] & MT_CALL) { if (maxc < j) maxc = j; } } tmp = tmp->next; } dispose_list (&f->INSN(f->msched[i]).dep); if (f->mtype[i] & MT_STORE) { maxs = last_store; last_store = i; } else if (f->mtype[i] & MT_LOAD) { maxl = last_load; last_load = i; } else if (f->mtype[i] & MT_CALL) { maxc = last_call; last_call = i; } if (maxl > lastl[t]) { add_dep (&f->INSN(f->msched[i]).dep, f->msched[maxl]); lastl[t] = maxl; } if (maxs > lasts[t]) { add_dep (&f->INSN(f->msched[i]).dep, f->msched[maxs]); lasts[t] = maxs; } if (maxc > lastc[t]) { add_dep (&f->INSN(f->msched[i]).dep, f->msched[maxc]); lastc[t] = maxc; } //PRINTF ("%i(%i)> ml %i(%i) ms %i(%i) lastl %i %i lasts %i %i last_load %i last_store %i\n", i, f->msched[i], maxl, f->msched[maxl], maxs, f->msched[maxs], lastl[0], lastl[1], lasts[0], lasts[1], last_load, last_store); /* What we have to wait to finish this BB? */ if (i + 1 >= f->nmsched || REF_BB(f->msched[i + 1]) != REF_BB(f->msched[i])) { if (last_load > lastl[t]) { add_dep (&f->bb[REF_BB(f->msched[i])].mdep, f->msched[last_load]); lastl[t] = last_load; } if (last_store > lasts[t]) { add_dep (&f->bb[REF_BB(f->msched[i])].mdep, f->msched[last_store]); lasts[t] = last_store; } if (last_call > lastc[t]) { add_dep (&f->bb[REF_BB(f->msched[i])].mdep, f->msched[last_call]); lastc[t] = last_call; } } } } return modified; }