/** test with long sequence of adds, removes and updates, and lookups */ static void test_long_table(struct lruhash* table) { /* assuming it all fits in the hastable, this check will work */ testdata_t* ref[HASHTESTMAX * 100]; size_t i; memset(ref, 0, sizeof(ref)); /* test assumption */ if(0) log_info(" size %d x %d < %d", (int)test_slabhash_sizefunc(NULL, NULL), (int)HASHTESTMAX, (int)table->space_max); unit_assert( test_slabhash_sizefunc(NULL, NULL)*HASHTESTMAX < table->space_max); if(0) lruhash_status(table, "unit test", 1); srandom(48); for(i=0; i<1000; i++) { /* what to do? */ if(i == 500) { lruhash_clear(table); memset(ref, 0, sizeof(ref)); continue; } switch(random() % 4) { case 0: case 3: testadd(table, ref); break; case 1: testremove(table, ref); break; case 2: testlookup(table, ref); break; default: unit_assert(0); } if(0) lruhash_status(table, "unit test", 1); check_table(table); unit_assert( table->num <= HASHTESTMAX ); } /* test more, but 'ref' assumption does not hold anymore */ for(i=0; i<1000; i++) { /* what to do? */ switch(random() % 4) { case 0: case 3: testadd_unlim(table, ref); break; case 1: testremove_unlim(table, ref); break; case 2: testlookup_unlim(table, ref); break; default: unit_assert(0); } if(0) lruhash_status(table, "unlim", 1); check_table(table); } }
static void *test_thr_main(void *arg) { struct test_thr *t = (struct test_thr *)arg; int i; for(i = 0; i < 1000; i++) { switch(random() % 4) { case 0: case 3: testadd(t->table, NULL); break; case 1: testremove(t->table, NULL); break; case 2: testlookup(t->table, NULL); break; default: unit_assert(0); } if(i % 100 == 0) check_table(t->table); } check_table(t->table); return NULL; }
/** main routine for threaded hash table test */ static void* test_thr_main(void* arg) { struct test_thr* t = (struct test_thr*)arg; int i; log_thread_set(&t->num); for(i=0; i<1000; i++) { switch(random() % 4) { case 0: case 3: testadd_unlim(t->table, NULL); break; case 1: testremove_unlim(t->table, NULL); break; case 2: testlookup_unlim(t->table, NULL); break; default: unit_assert(0); } if(0) lruhash_status(t->table, "hashtest", 1); if(i % 100 == 0) /* because of locking, not all the time */ check_table(t->table); } check_table(t->table); return NULL; }
/** test with long sequence of adds, removes and updates, and lookups */ static void test_long_table(struct slabhash* table) { /* assuming it all fits in the hashtable, this check will work */ testdata_type* ref[HASHTESTMAX * 100]; size_t i; memset(ref, 0, sizeof(ref)); /* test assumption */ if(0) slabhash_status(table, "unit test", 1); srandom(48); for(i=0; i<1000; i++) { /* what to do? */ if(i == 500) { slabhash_clear(table); memset(ref, 0, sizeof(ref)); continue; } switch(random() % 4) { case 0: case 3: testadd(table, ref); break; case 1: testremove(table, ref); break; case 2: testlookup(table, ref); break; default: unit_assert(0); } if(0) slabhash_status(table, "unit test", 1); check_table(table); } /* test more, but 'ref' assumption does not hold anymore */ for(i=0; i<1000; i++) { /* what to do? */ switch(random() % 4) { case 0: case 3: testadd_unlim(table, ref); break; case 1: testremove_unlim(table, ref); break; case 2: testlookup_unlim(table, ref); break; default: unit_assert(0); } if(0) slabhash_status(table, "unlim", 1); check_table(table); } }
int main(void) { HashTablePtr table; int i; printf("\n***** 256 consecutive integers ****\n"); table = N(HashCreate)(); for (i = 0; i < 256; i++) N(HashInsert)(table, i, i); for (i = 0; i < 256; i++) check_table(table, i, i); for (i = 256; i >= 0; i--) check_table(table, i, i); compute_dist(table); N(HashDestroy)(table); printf("\n***** 1024 consecutive integers ****\n"); table = N(HashCreate)(); for (i = 0; i < 1024; i++) N(HashInsert)(table, i, i); for (i = 0; i < 1024; i++) check_table(table, i, i); for (i = 1024; i >= 0; i--) check_table(table, i, i); compute_dist(table); N(HashDestroy)(table); printf("\n***** 1024 consecutive page addresses (4k pages) ****\n"); table = N(HashCreate)(); for (i = 0; i < 1024; i++) N(HashInsert)(table, i*4096, i); for (i = 0; i < 1024; i++) check_table(table, i*4096, i); for (i = 1024; i >= 0; i--) check_table(table, i*4096, i); compute_dist(table); N(HashDestroy)(table); printf("\n***** 1024 random integers ****\n"); table = N(HashCreate)(); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) N(HashInsert)(table, random(), i); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) check_table(table, random(), i); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) check_table(table, random(), i); compute_dist(table); N(HashDestroy)(table); printf("\n***** 5000 random integers ****\n"); table = N(HashCreate)(); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) N(HashInsert)(table, random(), i); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) check_table(table, random(), i); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) check_table(table, random(), i); compute_dist(table); N(HashDestroy)(table); return 0; }
/*------------------------------------------------------------ * * is_small_prime * * Returns 1 if n is prime, Returns 0 if n is composite * Returns -1 if we cannot decide * */ static int is_small_prime(mpanum n) { mpa_word_t v; /* If n is larger than a mpa_word_t, we can only decide if */ /* n is even. If it's odd we cannot tell. */ if (__mpanum_size(n) > 1) return ((mpa_parity(n) == MPA_EVEN_PARITY) ? 0 : -1); v = mpa_get_word(n); /* will convert negative n:s to positive v:s. */ if ((v | 1) == 1) /* 0 and 1 are not prime */ return DEF_COMPOSITE; if (v == 2) /* 2 is prime */ return DEF_PRIME; if ((v & 1) == 0) return DEF_COMPOSITE; /* but no other even number */ #if defined(USE_PRIME_TABLE) if (mpa_cmp_short(n, MAX_TABULATED_PRIME) > 0) return -1; v = (v - 3) >> 1; return check_table(v); #else return -1; #endif }
/* Lock must have already been obtained. */ void RSIM_FutexTable::dump(FILE *f, const std::string &title, const std::string &prefix) { if (!title.empty()) fprintf(f, "%s\n", title.c_str()); if (!table) { fprintf(f, "%sNo table loaded.\n", prefix.c_str()); } else if (table->magic!=MAGIC) { fprintf(f, "%sBad magic number.\n", prefix.c_str()); } else if (check_table()!=0) { fprintf(f, "%sTable structure error.\n", prefix.c_str()); } else { fprintf(f, "%sFile descriptor = %d\n", prefix.c_str(), fd); for (size_t i=0; i<NBUCKETS; i++) { if (table->bucket[i]) { fprintf(f, "%s bucket[%zu] = {", prefix.c_str(), i); for (size_t j=table->bucket[i]; j!=0; j=table->member[j].next) { fprintf(f, "\n%s { key=0x%08" PRIx64", next=%u, prev=%u, bitset=0x%08" PRIx32" }", prefix.c_str(), table->member[j].key, table->member[j].next, table->member[j].prev, table->member[j].bitset); } fprintf(f, "}\n"); } } } }
/* * do sanity checks for GetOptions() and fills 'data' */ static int do_sanity( struct global *data,char *const *argv, const optionT *opt, unsigned flags, void *reserved ) { int nRet=0; assert( data ); if( !argv ) nRet = -1; else if( opt==NULL || !check_table(opt) ) nRet = -1; else if( flags <0 && flags >= OPT_F_INVALID ) nRet = -1; if( nRet < 0) return nRet; data->table = opt; data->i = 1; data->pt = NULL; data->flags = flags; data->reserved = reserved; data->argv = /*clone_argv(argv)*/ argv; if( data->argv == NULL) nRet = -1; return nRet; }
Scalar* Function<Scalar>::get_dxy_values(int component) const { #ifdef _DEBUG check_params(component, cur_node, num_components); check_table(component, cur_node, 5, "DXY values"); #endif return cur_node->values[component][5]; }
static void test_long_table(struct lruhash* table) { testdata *ref[MAXHASH * 100]; size_t i; memset(ref, 0, sizeof(ref)); unit_assert(sizefunc(NULL, NULL)*MAXHASH < table->space_max); srandom(48); for(i = 0; i < 1000; i++) { if(i == 500) { lruhash_clear(table); memset(ref, 0, sizeof(ref)); continue; } switch(random() % 4) { case 0: case 3: testadd(table, ref); break; case 1: testremove(table, ref); break; case 2: testlookup(table, ref); break; default: unit_assert(0); } check_table(table); unit_assert(table->num <= MAXHASH); } }
void funcbottom(Statement *stmt) { Statement *s, *s1; dfs.printf("Enter funcbottom\n"); nl(); check_table(SYM::GetPtr(currentFn->lsyms.GetHead())); lc_auto = 0; lfs.printf("\n\n*** local symbol table ***\n\n"); ListTable(¤tFn->lsyms,0); // Should recurse into all the compound statements if (stmt==NULL) dfs.printf("DIAG: null statement in funcbottom.\r\n"); else { if (stmt->stype==st_compound) ListCompound(stmt); } lfs.printf("\n\n\n"); // ReleaseLocalMemory(); // release local symbols isPascal = FALSE; isKernel = FALSE; isOscall = FALSE; isInterrupt = FALSE; isNocall = FALSE; dfs.printf("Leave funcbottom\n"); }
static void set_pt_entry(ulong addr, ulong val, ulong fl) { ulong t; if (addr >= KSPACE_LOC) { addr -= NON_CANON_SIZE; } t = check_table(addr, PML4T_LOC, 39, fl); t = check_table(addr, t, 30, fl); t = check_table(addr, t, 21, fl); t = get_entry_addr(addr, t, 12); ATQ(t) = val; }
/* * check_job_tables - check jobacct related tables and functions * IN pg_conn: database connection * IN user: database owner * RET: error code */ extern int check_job_tables(PGconn *db_conn, char *cluster) { int rc; rc = check_table(db_conn, cluster, job_table, job_table_fields, job_table_constraint); rc |= check_table(db_conn, cluster, step_table, step_table_fields, step_table_constraint); rc |= check_table(db_conn, cluster, suspend_table, suspend_table_fields, suspend_table_constraint); rc |= _create_function_add_job_start(db_conn, cluster); rc |= _create_function_add_step_start(db_conn, cluster); rc |= _create_function_get_job_suspend_time(db_conn, cluster); return rc; }
void Function<Scalar>::get_dx_dy_values(Scalar*& dx, Scalar*& dy, int component) const { #ifdef _DEBUG check_params(component, cur_node, num_components); check_table(component, cur_node, 1, "DX values"); check_table(component, cur_node, 2, "DY values"); #endif dx = cur_node->values[component][1]; dy = cur_node->values[component][2]; }
void initialize(void) { #ifdef ISN_DEBUG if (!check_table(EAN13, EAN13_index)) elog(LOG, "EAN13 failed check"); if (!check_table(ISBN, ISBN_index)) elog(LOG, "ISBN failed check"); if (!check_table(ISMN, ISMN_index)) elog(LOG, "ISMN failed check"); if (!check_table(ISSN, ISSN_index)) elog(LOG, "ISSN failed check"); if (!check_table(UPC, UPC_index)) elog(LOG, "UPC failed check"); #endif g_initialized = true; }
int RSIM_FutexTable::signal(rose_addr_t key, uint32_t bitset, int nprocs, LockStatus lock_state) { int retval = 0; if (0==bitset) return 0; /* Obtain lock if necessary */ assert(table && table->magic==MAGIC); if (UNLOCKED==lock_state) { int status __attribute__((unused)) = TEMP_FAILURE_RETRY(sem_wait(semaphore)); assert(0==status); } #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif size_t bno = key % NBUCKETS; for (size_t mno=table->bucket[bno]; mno!=0 && retval>=0 && retval<nprocs; mno=table->member[mno].next) { if (table->member[mno].key==key && 0!=(table->member[mno].bitset & bitset)) { table->member[mno].key = 0; if (-1==sem_post(&table->member[mno].sem)) { if (0==retval) retval = -errno; break; } retval++; } } #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif /* Release lock if we acquired it here. */ if (UNLOCKED==lock_state) { int status __attribute__((unused)) = sem_post(semaphore); assert(0==status); } return retval; }
/* * check_acct_tables - check account related tables and functions * IN pg_conn: database connection * IN user: database owner * RET: error code */ extern int check_acct_tables(PGconn *db_conn) { int rc; rc = check_table(db_conn, "public", acct_table_name, acct_table_fields, acct_table_constraints); rc |= _create_function_add_acct(db_conn); return rc; }
/* * check_cluster_tables - check cluster related tables and functions * IN pg_conn: database connection * IN user: database owner * RET: error code */ extern int check_cluster_tables(PGconn *db_conn) { int rc; rc = check_table(db_conn, "public", cluster_table_name, cluster_table_fields, cluster_table_constraint); rc |= _create_function_add_cluster(db_conn); return rc; }
void funcbottom() { nl(); check_table(&lsyms); lc_auto = 0; fprintf(list,"\n\n*** local symbol table ***\n\n"); ListTable(&lsyms,0); fprintf(list,"\n\n\n"); ReleaseLocalMemory(); /* release local symbols */ isPascal = FALSE; isOscall = FALSE; isInterrupt = FALSE; isNocall = FALSE; }
void process_request(Packet * pckt_req, Packet * pckt_ans) { int i; TableStatus nstatus[MAX_TABLES]; switch (pckt_req->opcode) { case CHECK_TABLE: check_table( pckt_req->data.req_check_table.id, &(pckt_ans->data.ans_check_table.status) ); break; case CHECK_TABLES: check_tables(nstatus); for (i = 0; i < MAX_TABLES; i++) pckt_ans->data.ans_check_tables.status[i] = nstatus[i]; break; case OCCUPY_TABLE: occupy_table( pckt_req->data.req_occupy_table.id, &(pckt_ans->data.ans_occupy_table.success) ); break; case FREE_TABLE: free_table( pckt_req->data.req_free_table.id, &(pckt_ans->data.ans_free_table.success) ); break; case RESERVE_TABLE: reserve_table( pckt_req->data.req_reserve_table.id, &(pckt_ans->data.ans_reserve_table.success) ); break; default: // TODO unknown operation code break; } }
/* * adds an entry for environmental firefly data, * creating the table if necessary. */ void write_env(struct firefly_env ff){ char *dberror = NULL; char cmdbuf[BUFLEN]; if(!check_table(ff.id)){ sprintf(cmdbuf,"create table \"%s\" (time int, light int, temp int, accl int, voltage int, audio int)",ff.id); sqlite3_exec(db,cmdbuf,callback,0,&dberror); sprintf(cmdbuf,"insert into devices(id, type) values ('%s', %d)", ff.id, FF_ENV); sqlite3_exec(db,cmdbuf,callback,0,&dberror); sqlite3_exec(db,"UPDATE info SET value=value+1 WHERE var='env_num'",callback,0,&dberror); } sprintf(cmdbuf,"insert into \"%s\" values(%d,%d,%d,%d,%d,%d)",ff.id,ff.time, ff.light, ff.temp, ff.accl, ff.voltage, ff.audio); sqlite3_exec(db,cmdbuf,callback,0,&dberror); return; }
bool check_table( const ::boost::type_erasure::binding<Concept>* t, R(*)(T0, T...), const U0& arg0, const U&... arg) { typedef typename ::boost::remove_cv< typename ::boost::remove_reference<T0>::type >::type t0; if(!::boost::type_erasure::detail::maybe_check_table<t0>( arg0, t, ::boost::type_erasure::detail::should_check<Concept, t0>())) return false; return check_table(t, static_cast<void(*)(T...)>(0), arg...); }
/* Reload a mapped device. */ int dm_reload(struct lib_context *lc, struct raid_set *rs, char *table) { int ret; /* Create <dev_name> */ ret = run_task(lc, rs, table, DM_DEVICE_RELOAD, rs->name); /* * In case device creation failed, check if target * isn't registered with the device-mapper core */ if (!ret) check_table(lc, table); return ret; }
void hash_table2::add(size_t x,size_t y) { size_t h = hash(x,y); if (hfind(h,x,y) == NOT_FOUND) { if (check_table()) { h = hash(x,y); } bucket2 new_bucket; new_bucket.x = x; new_bucket.y = y; new_bucket.next = table[h]; table[h] = buckets.size(); buckets.push_back(new_bucket); } }
/* * adds an entry for power firefly (jigawatt) data, * creating the table if necessary. */ void write_pow(struct firefly_pow ff){ char *dberror = NULL; char cmdbuf[BUFLEN]; if(!check_table(ff.id)){ sprintf(cmdbuf,"create table \"%s\" (time int, state int, rms_current int, rms_voltage int, true_power int, energy int)",ff.id); sqlite3_exec(db,cmdbuf,callback,0,&dberror); sprintf(cmdbuf,"insert into devices(id, type) values ('%s', %d)", ff.id, FF_POW); sqlite3_exec(db,cmdbuf,callback,0,&dberror); sqlite3_exec(db,"UPDATE info SET value=value+1 WHERE var='pow_num'",callback,0,&dberror); } sprintf(cmdbuf,"insert into \"%s\" values(%d,%d,%d,%d,%d,%d)",ff.id,ff.time, ff.state, ff.rms_current, ff.rms_voltage, ff.true_power, ff.energy); sqlite3_exec(db,cmdbuf,callback,0,&dberror); return; }
void funcbottom(Statement *stmt) { Statement *s, *s1; nl(); check_table(lsyms.head); lc_auto = 0; fprintf(list,"\n\n*** local symbol table ***\n\n"); ListTable(&lsyms,0); // Should recurse into all the compound statements if (stmt==NULL) printf("DIAG: null statement in funcbottom.\r\n"); else { if (stmt->stype==st_compound) ListCompound(stmt); } fprintf(list,"\n\n\n"); ReleaseLocalMemory(); /* release local symbols */ isPascal = FALSE; isKernel = FALSE; isOscall = FALSE; isInterrupt = FALSE; isNocall = FALSE; }
//--------------------------------------------------------------------------- // The main function - called when the user selects the menu item static bool idaapi callback(void *) { // Calculate the default values to display in the form ea_t screen_ea = get_screen_ea(); segment_t *s = getseg(screen_ea); if ( s == NULL || !isCode(get_flags_novalue(screen_ea)) ) { warning("AUTOHIDE NONE\nThe cursor must be on the table jump instruction"); return false; } ea_t startea = screen_ea; while ( true ) { ea_t prev = prev_not_tail(startea); if ( !is_switch_insn(prev) ) break; startea = prev; } ea_t jumps = get_first_dref_from(screen_ea); uval_t jelsize = s->abytes(); uval_t jtsize = 0; if ( jumps != BADADDR ) { decode_insn(screen_ea); jtsize = guess_table_size(jumps); } uval_t shift = 0; uval_t elbase = 0; char input[MAXSTR]; input[0] = '\0'; ea_t defea = BADADDR; uval_t lowcase = 0; ushort jflags = 0; ushort vflags = 0; ea_t vtable = BADADDR; ea_t vtsize = 0; ea_t velsize = s->abytes(); reg_info_t ri; ri.size = 0; // If switch information is present in the database, use it for defaults switch_info_ex_t si; if ( get_switch_info_ex(screen_ea, &si, sizeof(si)) > 0 ) { jumps = si.jumps; jtsize = si.ncases; startea = si.startea; elbase = si.elbase; jelsize = si.get_jtable_element_size(); shift = si.get_shift(); defea = (si.flags & SWI_DEFAULT) ? si.defjump : BADADDR; if ( si.regnum != -1 ) get_reg_name(si.regnum, get_dtyp_size(si.regdtyp), input, sizeof(input)); if ( si.flags & SWI_SIGNED ) jflags |= 2; if ( si.flags2 & SWI2_SUBTRACT ) jflags |= 4; if ( si.flags & SWI_SPARSE ) { jflags |= 1; vtable = si.values; vtsize = jtsize; velsize = si.get_vtable_element_size(); if ( si.flags2 & SWI2_INDIRECT ) { vflags |= 1; jtsize = si.jcases; } if ( si.flags & SWI_JMP_INV ) vflags |= 2; } else { lowcase = si.lowcase; } } // Now display the form and let the user edit the attributes while ( AskUsingForm_c(main_form, &jumps, &jtsize, &jelsize, &shift, &elbase, &startea, input, &lowcase, &defea, &jflags) ) { if ( !check_table(jumps, jelsize, jtsize) ) continue; if ( shift > 3 ) { warning("AUTOHIDE NONE\nInvalid shift value (allowed values are 0..3)"); continue; } if ( !isCode(get_flags_novalue(startea)) ) { warning("AUTOHIDE NONE\nInvalid switch idiom start %a (must be an instruction", startea); continue; } ri.reg = -1; if ( input[0] != '\0' && !parse_reg_name(input, &ri) ) { warning("AUTOHIDE NONE\nUnknown input register: %s", input); continue; } if ( defea != BADADDR && !isCode(get_flags_novalue(defea)) ) { warning("AUTOHIDE NONE\nInvalid default jump %a (must be an instruction", defea); continue; } if ( jflags & 1 ) // value table is present { bool vok = false; while ( AskUsingForm_c(value_form, &vflags, &vtable, &vtsize, &velsize) ) { if ( (vflags & 1) == 0 ) vtsize = jtsize; if ( check_table(vtable, velsize, vtsize) ) { vok = true; break; } } if ( !vok ) break; } // ok, got and validated all params -- fill the structure si.flags = SWI_EXTENDED; si.flags2 = 0; if ( jflags & 2 ) si.flags |= SWI_SIGNED; if ( jflags & 4 ) si.flags2 |= SWI2_SUBTRACT; si.jumps = jumps; si.ncases = ushort(jtsize); si.startea = startea; si.elbase = elbase; if ( elbase != 0 ) si.flags |= SWI_ELBASE; si.set_jtable_element_size((int)jelsize); si.set_shift((int)shift); if ( defea != BADADDR ) { si.flags |= SWI_DEFAULT; si.defjump = defea; } if ( ri.reg != -1 ) si.set_expr(ri.reg, get_dtyp_by_size(ri.size)); if ( jflags & 1 ) // value table is present { si.flags |= SWI_SPARSE; si.values = vtable; si.set_vtable_element_size((int)velsize); if ( (vflags & 1) != 0 ) { si.flags2 |= SWI2_INDIRECT; si.jcases = (int)jtsize; si.ncases = (ushort)vtsize; } if ( (vflags & 2) != 0 ) si.flags |= SWI_JMP_INV; } else { si.lowcase = lowcase; } // ready, store it set_switch_info_ex(screen_ea, &si); create_switch_table(screen_ea, &si); setFlbits(screen_ea, FF_JUMP); create_insn(screen_ea); info("AUTOHIDE REGISTRY\nSwitch information has been stored"); break; } return true; }
void RSIM_FutexTable::ctor(const std::string &name, bool do_unlink) { if (fd<0) { /* Obtain a lock */ int status __attribute__((unused)) = TEMP_FAILURE_RETRY(sem_wait(semaphore)); assert(0==status); int err = 0; bool created = false; do { /* Try to open an existing file, or create a new one. */ if ((fd = shm_open(name.c_str(), O_RDWR, 0666)) < 0) { if ((fd = shm_open(name.c_str(), O_CREAT|O_RDWR, 0666)) < 0) { err = -errno; break; } if (do_unlink) shm_unlink(name.c_str()); if (ftruncate(fd, sizeof(Table))<0) { err = -errno; break; } created = true; } /* Map the table to memory */ table = (RSIM_FutexTable::Table*)mmap(NULL, sizeof(Table), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (MAP_FAILED==table) { err = -errno; table = NULL; break; } if (created) { err = init_table(); #ifdef RSIM_FUTEX_CHECKING assert(!err); assert(0==check_table()); #endif } else { err = check_table(); } } while (0); /* Error cleanup */ if (err) { if (table) { munmap(table, sizeof(Table)); table = NULL; } if (fd>=0) { close(fd); fd = -1; } } /* Release the lock */ status = sem_post(semaphore); assert(0==status); } }
/* Releases the specified member index from the queue with the specified key. The lock is acquired/released by this function. */ int RSIM_FutexTable::erase(rose_addr_t key, size_t member_number, LockStatus lock_state) { /* Obtain lock if necessary */ assert(table && table->magic==MAGIC); if (UNLOCKED==lock_state) { int status = sem_wait(semaphore); if (-1==status && EINTR==errno) return -EINTR; assert(0==status); } #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif size_t bno = key % NBUCKETS; bool erased = false; /* Remove from queue */ if (table->bucket[bno]==member_number) { size_t new_head = table->member[member_number].next; table->bucket[bno] = new_head; table->member[new_head].prev = 0; // might initialize member[0].prev, but that's ok erased = true; } else { for (size_t mno=table->bucket[bno]; mno!=0 && !erased; mno=table->member[mno].next) { if (mno==member_number) { if (table->member[mno].prev) table->member[table->member[mno].prev].next = table->member[mno].next; if (table->member[mno].next) table->member[table->member[mno].next].prev = table->member[mno].prev; erased = true; } } } if (erased) { /* Add to free list */ if (table->free_head) table->member[table->free_head].prev = member_number; table->member[member_number].next = table->free_head; table->member[member_number].prev = 0; table->free_head = member_number; /* Destroy semaphore. */ int status __attribute__((unused)) = sem_destroy(&table->member[member_number].sem); assert(0==status); } #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif /* Release lock if we acquired it here. */ if (UNLOCKED==lock_state) { int status __attribute__((unused)) = sem_post(semaphore); assert(0==status); } return erased ? 0 : -EINVAL; }
/* Insert a new key into a wait queue and return its index. Lock is acquired/released by this function. */ int RSIM_FutexTable::insert(rose_addr_t key, uint32_t bitset, LockStatus lock_state) { int retval = 0; if (0==bitset) return -EINVAL; /* Obtain lock if necessary */ assert(table && table->magic==MAGIC); if (UNLOCKED==lock_state) { int status = sem_wait(semaphore); if (-1==status && EINTR==errno) return -EINTR; assert(0==status); } #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif size_t bno = key % NBUCKETS; size_t mno = table->free_head; do { /* Allocate a new member */ if (mno<=0) { retval = -EAGAIN; // no free space break; } table->free_head = table->member[mno].next; table->member[table->free_head].prev = 0; // might initialize member[0].prev, but that's ok /* Link new member into bucket. */ size_t old_head = table->bucket[bno]; table->bucket[bno] = mno; table->member[mno].next = old_head; table->member[mno].prev = 0; if (old_head>0) table->member[old_head].prev = mno; /* Initialize the member. */ table->member[mno].key = key; table->member[mno].bitset = bitset; int status = sem_init(&table->member[mno].sem, 1, 0); if (-1==status) { retval = -errno; break; } } while (0); #ifdef RSIM_FUTEX_CHECKING assert(0==check_table()); #endif /* Release lock if we aquired it here. */ if (UNLOCKED==lock_state) { int status __attribute__((unused)) = sem_post(semaphore); assert(0==status); } return 0==retval ? mno : retval; }