Пример #1
0
void
initsem(void)
{

	attrtab = ht_new();
	errattr.a_name = "<internal>";

	allbases = NULL;
	nextbase = &allbases;

	alldevas = NULL;
	nextdeva = &alldevas;

	cfhashtab = ht_new();
	allcf = NULL;
	nextcf = &allcf;

	devitab = ht_new();
	alldevi = NULL;
	nextdevi = &alldevi;
	errdev.d_name = "<internal>";

	allpseudo = NULL;
	nextpseudo = &allpseudo;

	s_generic = intern("generic");
	s_nfs = intern("nfs");
}
Пример #2
0
void
initfiles(void)
{

	basetab = ht_new();
	pathtab = ht_new();
	nextfile = &allfiles;
	unchecked = &allfiles;
	nextobject = &allobjects;
}
/*
 * Starts a new mailbox for the given user.
 */
MailboxResult *mailbox_start_1_svc(MailboxParams *argp, struct svc_req *rqstp) {
  static MailboxResult result = MailboxResultSuccess;

  // Create users hashtable if not exists.
  if (g_users_ht == NULL) {
    if (!(g_users_ht = ht_new(USERS_TABLE_INIT_SIZE,
                              USERS_TABLE_EXPAN_SIZE,
                              USERS_TABLE_LOAD_FACTOR))) {
      result = MailboxResultServerFailure;
      return &result;
    }
  }

  // Check if users hashtable contains given user name:
  if (ht_get(g_users_ht, argp->user, NULL)) {
    result = MailboxResultUserExists;
    return &result;
  }

  // Create user's mailbox.
  Stk *mailbox = stk_new(MAILBOX_INIT_SIZE);

  // Register the user's mailbox under their name.
  if (!ht_put_pointer(g_users_ht, argp->user, mailbox, NULL, NULL)) {
    result = MailboxResultServerFailure;
    return &result;
  }

  result = MailboxResultSuccess;
  return &result;
}
Пример #4
0
/**
 * Creates a new compiler object that will contain the current state of the
 * compiler and its data structures.
 * returns: new compiler object, or NULL if the allocation fails.
 */
Compiler * compiler_new(VM * vm) {

  assert(vm != NULL);

  Compiler * compiler = calloc(1, sizeof(Compiler));

  /* check for failed allocation */
  if(compiler == NULL) {
    return NULL;
  }

  /* TODO: make this stack auto expand when full */
  compiler->compiledScripts = set_new();
  compiler->symTableStk = stk_new(maxFuncDepth);
  compiler->functionHT = ht_new(COMPILER_INITIAL_HTSIZE, COMPILER_HTBLOCKSIZE, COMPILER_HTLOADFACTOR);
  compiler->outBuffer = buffer_new(bufferBlockSize, bufferBlockSize);
  compiler->vm = vm;

  /* check for further malloc errors */
  if(compiler->compiledScripts == NULL
     || compiler->symTableStk == NULL 
     || compiler->functionHT == NULL 
     || compiler->outBuffer == NULL) {
    compiler_free(compiler);
    return NULL;
  }

  return compiler;
}
Пример #5
0
/*
 * XXX Is this called anywhere in Cubist?  It looks like it's
 * XXX been made obsolete by rbm_removeall.
 */
int rbm_init()
{
    if (strbufv == NULL) {
        strbufv = ht_new(HASH_LEN);
    }
    return strbufv == NULL ? -1 : 0;
}
Пример #6
0
// TODO: use mmap instead of read.. much faster!
SDB_VISIBLE Sdb* sdb_new (const char *dir, int lock) {
	Sdb* s;
	if (lock && !sdb_lock (sdb_lockfile (dir)))
		return NULL;
	s = malloc (sizeof (Sdb));
	if (dir && *dir) {
		s->dir = strdup (dir);
		s->fd = open (dir, O_RDONLY|O_BINARY);
		// if (s->fd == -1) // must fail if we cant open for write in sync
	} else {
		s->dir = NULL;
		s->fd = -1;
	}
	s->fdump = -1;
	s->ndump = NULL;
	s->ns = ls_new ();
	s->ht = ht_new ();
	s->lock = lock;
	s->expire = 0LL;
	//s->ht->list->free = (SdbListFree)sdb_kv_free;
	// if open fails ignore
	cdb_init (&s->db, s->fd);
	cdb_findstart (&s->db);
	return s;
}
Пример #7
0
/*! Delete entries from the hash */
static void *hash_test_shrink(void *d)
{
	const struct hash_test *data = d;
	int i;

	for (i = 1; i < data->preload; ++i) {
		char *obj = ht_new(-i);
		char *from_hashtab;
		int deleted;

		if (obj == NULL) {
			return "Allocation failed";
		}
		from_hashtab = ast_hashtab_remove_object_via_lookup(data->to_be_thrashed, obj);
		deleted = from_hashtab != NULL;

		ht_delete(obj);
		ht_delete(from_hashtab);
		if (!deleted) {
			return "could not delete object";
		}
		if (is_timed_out(data)) {
			return "Shrink timed out";
		}
	}
	return NULL;
}
Пример #8
0
/*! Delete entries from the hash */
static void *hash_test_shrink(void *d)
{
    const struct hash_test *data = d;
    int i;

    for (i = 1; i < data->preload; ++i) {
        char *obj = ht_new(-i);
        char *from_ao2;

        if (obj == NULL) {
            return "Allocation failed";
        }
        from_ao2 = ao2_find(data->to_be_thrashed, obj, OBJ_UNLINK | OBJ_POINTER);

        ao2_ref(obj, -1);
        if (from_ao2) {
            ao2_ref(from_ao2, -1);
        } else {
            return "Could not find object to delete";
        }

        if (is_timed_out(data)) {
            return "Shrink timed out";
        }
    }

    return NULL;
}
Пример #9
0
/*
 * This is called at the beginning of a cubist run to clear out
 * all "files" generated on the previous run and to prepare it
 * for the next run.
 */
void rbm_removeall()
{
    /* Check if there actually is anything to remove */
    if (strbufv != NULL) {
        /*
         * Destroy all STRBUF's in the hash table.
         * Note that this loop leaves the hash table full of
         * pointers to deallocated STRBUF's until ht_destroy
         * is called below.
         */
        ht_reset(strbufv);  /* just in case */
        while (1) {
            void *e = ht_next(strbufv);
            if (e == NULL)
                break;
            strbuf_destroy((STRBUF *) ht_value(e));
        }

        /* Destroy the hash table itself */
        ht_destroy(strbufv);
    }

    /* Create/recreate the hash table for subsequent use */
    strbufv = ht_new(HASH_LEN);
}
Пример #10
0
/*----------------------------------------------------------------------------
* static void
* init_unit_tbl()
* initializes the hash table used to hold units
*
* Return Value --
* none
*
* Design --
* calls the hash package to get a hash table, puts in default unit
* calls parse_dispmon_plusargs
*
* Side effects --
* sets unit_tbl
*----------------------------------------------------------------------------
*/
static void 
init_unit_tbl()
{
  ms.unit_tbl=ht_new(256);
  ht_put(ms.unit_tbl, "default", &ms.default_unit);
  parse_dispmon_plusargs();
}
Пример #11
0
disjoint_set djs_new( unsigned int elts, hash_cb hc, isequal_cb ic ) {
  struct disjoint_sets *djs = 
    (struct disjoint_sets *)malloc(sizeof(struct disjoint_sets));
  /* should change one of these nulls to a free to get cleanup behavior */
  djs->st = ds_q_new(NULL, NULL);
  djs->ht = ht_new( elts, hc, ic, NULL );
  return(djs);
}
Пример #12
0
Bitcask* bc_open2(Mgr *mgr, int depth, int pos, time_t before)
{
    Bitcask* bc = (Bitcask*)malloc(sizeof(Bitcask));
    memset(bc, 0, sizeof(Bitcask));    
    bc->mgr = mgr;
    bc->depth = depth;
    bc->pos = pos;
    bc->before = before;
    bc->tree = ht_new(depth, pos);
    bc->curr_tree = ht_new(depth, pos);
    bc->wbuf_size = 1024 * 4;
    bc->write_buffer = malloc(bc->wbuf_size);
    bc->last_flush_time = time(NULL);
    pthread_mutex_init(&bc->buffer_lock, NULL);
    pthread_mutex_init(&bc->write_lock, NULL);
    pthread_mutex_init(&bc->flush_lock, NULL);
    return bc;
}
static void test_hashitem_set_and_get() {

    hash_table table = ht_new();

    char* key = "hello";
    int value = 100;
    ht_set_value(&table, key, (void *) &value);

    int* value_get = (int *)ht_get_value(&table, key);
    assert(value == *value_get
           && "The value set is not the same as the get");
}
Пример #14
0
/* create a new dictionary */
struct dict *
dict_new(long sz) {
	
	struct dict *d = calloc(sizeof(struct dict), 1);
	d->ht = ht_new(sz); /* a single pre-defined HT */

	/* default helper functions */
	d->key_hash = djb_hash;
	d->key_dup = key_dup_default;
	d->key_free = key_free_default;

	return d;
}
Пример #15
0
Файл: evidence.c Проект: gaibo/C
int main(void) {
    printf("*****testing hash table*****\n\n");
    htbl* t = ht_new(&good_hash, 10);
    
    FILE* cnets2015 = fopen("cnets2015", "r");
    while (!feof(cnets2015)) {
        char* s = alloc_str(256);
        fgets(s, 256, cnets2015);
        char* l = trim_newline(s);
        free(s);
        if (strlen(l) > 0) {
            ht_ins(l, t);
        }
        free(l);
    }
    fclose(cnets2015);
    
    ht_show(t);
    printf("The hash table has %u buckets with %u entries (load factor %lg).\n\n",
        t->n_buckets, 
        ht_n_entries(t),
        ht_load_factor(t));
    printf("The bucket with the most items in it contains %u items.\n\n",
        ht_max_bucket(t));
    printf("ht_member:\n");
    printf("membership of cnet \"aardvark\" : %i\n", ht_member("aardvark", t));
    printf("membership of cnet \"borja\"    : %i\n", ht_member("borja", t));
    printf("\n");
    
    // resize
    printf("***now resizing***\n");
    ht_resize(&t);
    printf("***resizing complete***\n\n");
    
    // do everything again
    ht_show(t);
    printf("The hash table has %u buckets with %u entries (load factor %lg).\n\n",
        t->n_buckets, 
        ht_n_entries(t),
        ht_load_factor(t));
    printf("The bucket with the most items in it contains %u items.\n\n",
        ht_max_bucket(t));
    printf("ht_member:\n");
    printf("membership of cnet \"aardvark\" : %i\n", ht_member("aardvark", t));
    printf("membership of cnet \"borja\"    : %i\n", ht_member("borja", t));
    printf("\n");
    
    ht_free(t);
    return 0;
}
sm_private_t sm_private_new(size_t buf_length) {
  sm_private_t my = (sm_private_t)malloc(sizeof(struct sm_private));
  if (!my) {
    return NULL;
  }
  memset(my, 0, sizeof(struct sm_private));
  my->all_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->server_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->send_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->recv_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->tmp_send_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->tmp_recv_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->tmp_fail_fds = (fd_set *)malloc(SIZEOF_FD_SET);
  my->fd_to_value = ht_new(HT_INT_KEYS);
  my->fd_to_sendq = ht_new(HT_INT_KEYS);
  my->tmp_buf = (char *)calloc(buf_length, sizeof(char *));
  if (!my->tmp_buf || !my->all_fds || !my->server_fds ||
      !my->send_fds || !my->recv_fds ||
      !my->tmp_send_fds || !my->tmp_recv_fds || !my->tmp_fail_fds ||
      !my->fd_to_value || !my->fd_to_sendq) {
    sm_private_free(my);
    return NULL;
  }
  FD_ZERO(my->all_fds);
  FD_ZERO(my->server_fds);
  FD_ZERO(my->send_fds);
  FD_ZERO(my->recv_fds);
  FD_ZERO(my->tmp_send_fds);
  FD_ZERO(my->tmp_recv_fds);
  FD_ZERO(my->tmp_fail_fds);
  my->max_fd = -1;
  my->timeout.tv_sec = 5;
  my->timeout.tv_usec = 0;
  my->tmp_buf_length = buf_length;
  return my;
}
Пример #17
0
int main(int argc, char **argv) {
    hashtable_t *hashtable = ht_new(65536);

    ht_set(hashtable, "key1", "inky");
    ht_set(hashtable, "key2", "pinky");
    ht_set(hashtable, "key3", "blinky");
    ht_set(hashtable, "key4", "floyd");

    printf("%s\n", ht_get(hashtable, "key1"));
    printf("%s\n", ht_get(hashtable, "key2"));
    printf("%s\n", ht_get(hashtable, "key3"));
    printf("%s\n", ht_get(hashtable, "key4"));

    return 0;
}
Пример #18
0
void bc_rotate(Bitcask *bc)
{
    // build in new thread
    char hintpath[255];
    new_path(hintpath, bc->mgr, HINT_FILE, bc->curr);
    struct build_thread_args *args = (struct build_thread_args*)malloc(
                                         sizeof(struct build_thread_args));
    args->tree = bc->curr_tree;
    args->path = strdup(hintpath);
    pthread_t build_ptid;
    pthread_create(&build_ptid, NULL, build_thread, args);
    // next bucket
    bc->curr ++;
    bc->curr_tree = ht_new(bc->depth, bc->pos);
    bc->wbuf_start_pos = 0;
}
Пример #19
0
R_API RAnalState * r_anal_state_new(ut64 start, ut8* buffer, ut64 len) {
	RAnalState *state = R_NEW0 (RAnalState);
	if (!state) {
		return NULL;
	}
	state->start = start;
	state->end = start + len;
	state->buffer = buffer;
	state->len = len;
	state->current_op = NULL;
	state->current_bb = NULL;
	state->current_fcn = NULL;
	state->ht = ht_new (NULL, (HtKvFreeFunc)kv_anal_bb_free, NULL);
	state->ht_sz = 512;
	state->bbs = r_list_newf ((RListFree)r_anal_bb_free);
	state->max_depth = 50;
	state->current_depth = 0;
	return state;
}
Пример #20
0
/*! /brief Grow the hash data as specified */
static void *hash_test_grow(void *d)
{
	struct hash_test *data = d;
	int i;

	for (i = 0; i < data->max_grow; ++i) {
		char *obj;
		if (is_timed_out(data)) {
			return "Growth timed out";
		}
		obj = ht_new(i);
		if (obj == NULL) {
			return "Allocation failed";
		}
		ast_hashtab_insert_immediate(data->to_be_thrashed, obj);
		ast_atomic_fetchadd_int(&data->grow_count, 1);
	}
	return NULL;
}
static void test_hashitem_delete() {

    hash_table table = ht_new();

    char* key = "hello";
    int value = 100;
    ht_set_value(&table, key, (void *) &value);

    int* value_get = (int *)ht_get_value(&table, key);
    assert(value == *value_get
           && "The value set is not the same as the get");

    ht_delete_value(&table, key);

    value_get = (int *)ht_get_value(&table, key);
    if (value_get != NULL) {
        assert(0 && "The value is not deleted.");
    }
}
Пример #22
0
struct shiki *shiki_new(size_t buffer_size)
{
	size_t size_level_new;
	size_t size_level_old;
	struct shiki *lru;

	size_level_new = buffer_size * RATIO;
	size_level_old = buffer_size - size_level_new;
	
	lru = calloc(1, sizeof(struct shiki));
	lru->ht = ht_new(PRIME);

	lru->level_old.allow_size = size_level_old;
	lru->level_new.allow_size = size_level_new;

	if (buffer_size > 1023)
		lru->buffer = 1;

	return lru;
}
dl_t dl_new() {
  dl_t self = (dl_t)malloc(sizeof(struct dl_struct));
  dl_private_t my = (dl_private_t)malloc(sizeof(struct dl_private));
  cb_t in = cb_new();
  ht_t d_ht = ht_new(HT_INT_KEYS);
  if (!self || !my || !in || !d_ht) {
    free(self);
    free(my);
    free(in);
    return NULL;
  }
  memset(self, 0, sizeof(struct dl_struct));
  memset(my, 0, sizeof(struct dl_private));
  self->start = dl_start;
  self->on_recv = dl_on_recv;
  self->private_state = my;
  my->in = in;
  my->device_num_to_device_id = d_ht;
  return self;
}
Пример #24
0
/*! /brief Grow the hash data as specified */
static void *hash_test_grow(void *d)
{
    struct hash_test *data = d;
    int i;

    for (i = 0; i < data->max_grow; ++i) {
        char *ht;
        if (is_timed_out(data)) {
            printf("Growth timed out at %d\n", i);
            return "Growth timed out";
        }
        ht = ht_new(i);
        if (ht == NULL) {
            return "Allocation failed";
        }
        ao2_link(data->to_be_thrashed, ht);
        ao2_ref(ht, -1);
        ast_atomic_fetchadd_int(&data->grow_count, 1);
    }
    return NULL;
}
static void test_hashitem_collisions() {

    hash_table table = ht_new();

    /*The keys k1 and k2 create the same index.*/
    char *k1 = "2WwtnwoDx";
    int v1 = 10;
    ht_set_value(&table, k1, &v1);

    char *k2 = "2Uiihmi2/";
    int v2 = 20;
    ht_set_value(&table, k2, &v2);

    int* v1_get = (int *)ht_get_value(&table, k1);
    assert(v1 == *v1_get
           && "The value set is not the same as get");

    int* v2_get = (int *)ht_get_value(&table, k2);
    assert(v2 == *v2_get
           && "The value set is not the same as get");
}
Пример #26
0
/*! Randomly lookup data in the hash */
static void *hash_test_lookup(void *d)
{
    struct hash_test *data = d;
    int max;
    unsigned seed = time(NULL);

    /* ast_atomic_fetchadd_int provide a memory fence so that the optimizer doesn't
     * optimize away reads.
     */
    while ((max = ast_atomic_fetchadd_int(&data->grow_count, 0)) < data->max_grow) {
        int i;
        char *obj;
        char *from_ao2;

        if (is_timed_out(data)) {
            return "Lookup timed out";
        }

        if (max == 0) {
            /* No data yet; yield and try again */
            sched_yield();
            continue;
        }

        /* Randomly lookup one object from the hash */
        i = rand_r(&seed) % max;
        obj = ht_new(i);
        if (obj == NULL) {
            return "Allocation failed";
        }
        from_ao2 = ao2_find(data->to_be_thrashed, obj, OBJ_POINTER);
        ao2_ref(obj, -1);
        ao2_ref(from_ao2, -1);
        if (from_ao2 == NULL) {
            return "Key unexpectedly missing";
        }
    }

    return NULL;
}
Пример #27
0
void scanDataFile(HTree* tree, int bucket, const char* path, const char* hintpath)
{
    MFile *f = open_mfile(path);
    if (f == NULL) return;
    
    fprintf(stderr, "scan datafile %s\n", path);
    HTree *cur_tree = ht_new(0,0);
    char *p = f->addr, *end = f->addr + f->size;
    int broken = 0;
    while (p < end) {
        DataRecord *r = decode_record(p, end-p, false);

        if (r != NULL) {
            uint32_t pos = p - f->addr;
            p += record_length(r); 
            r = decompress_record(r);
            uint16_t hash = gen_hash(r->value, r->vsz);
            if (r->version > 0){
                ht_add2(tree, r->key, r->ksz, pos | bucket, hash, r->version);            
            }else{
                ht_remove2(tree, r->key, r->ksz);
            }
            ht_add2(cur_tree, r->key, r->ksz, pos | bucket, hash, r->version);
            free_record(r);
        } else {
            broken ++;
            if (broken > 40960) { // 10M
                fprintf(stderr, "unexpected broken data in %s at %ld\n", path, p - f->addr - broken * PADDING);
                break;
            }
            p += PADDING;
        }
    }

    close_mfile(f);
    build_hint(cur_tree, hintpath);
}
Пример #28
0
/* add an item into the dictionary */
void
dict_add(struct dict *d, char *k, size_t sz, void *v) {

	struct bucket *b;
	char *k_dup = k;
	unsigned long h = d->key_hash(k, sz);

	/* possibly duplicate key */
	k_dup = d->key_dup(k, sz);

	/* check for important load and resize if need be. */
	if((float)d->count / (float)d->ht->sz > DICT_MAX_LOAD) {
		/* expand and replace HT */
		d->ht_old = d->ht;
		d->ht = ht_new(d->ht->sz + 1); /* will select next prime */
	}

	if((b = ht_insert(d->ht, h, k_dup, sz, v))) {
		d->count++;
		ht_record_used_bucket(d->ht, b);
	}
	
	dict_rehash(d);
}
Пример #29
0
Файл: mslave.c Проект: 0x42/fire
int main(int argc, char *argv[])
{
	pthread_t thread_wdt;
	pthread_t thread_log;
	pthread_t thread_fifoSrv;
	pthread_t thread_snmpSrv;
	pthread_t thread_sendfifo;
	pthread_t thread_ch1, thread_ch2;
	pthread_t thread_rtSend, thread_rtRecv;
	
	struct wdt_thread_arg wdt_targ;
	struct log_thread_arg log_targ;
	struct fifo_thread_arg fifoSrv_targ;
	struct snmp_thread_arg snmpSrv_targ;
	struct sfifo_thread_arg sendfifo_targ;
	struct chan_thread_arg ch1_targ, ch2_targ;
	struct rt_thread_arg rtSend_targ, rtRecv_targ;

	int result;
	
	char cfile[64];
	char lfile[64];
	char lfile_old[64];
	char lifeFile[64];

	int rs_parity, rs_databits, rs_stopbit;
	int rs_speed;

	unsigned int utxdel;
	
	int tscan;
	int tout, nretries;

	int wdt_en;
	unsigned long wdt_tm;
	
	int ch1_enable, ch2_enable;
	
	char ip[16];
	unsigned int fifo_port;

	char rt_ipSend[16];
	char rt_ipRecv[16];
	unsigned int rt_portSend, rt_portRecv;

	char logSend_ip[16];
	unsigned int logSend_port, logMaxLines;
	
	int snmp_n, snmp_uso;
	char *tempip;
	
	char ls_gen[32];
	char req_ag[32];
	char req_ns[32];
	char req_gl[32];
	char req_ms[32];

	int cdDest;
	int cdaId;
	int cdnsId;
	int cdquLogId;
	int cdmsId;
	
	int i;
	char key[7] = {0};
	
	TOHT *cfg;

	if( argc == 2)
		sprintf(cfile, argv[1]);
	else {
		sprintf(cfile, "mslave_default.cfg");
		gen_moxa_default_cfg(cfile);  /** Генерация slave конфиг файла
					       *  по умолчанию */
	}
	
	cfg = cfg_load(cfile);  /** Загрузили общий конфиг */
	
	/** Установка лог файла */
	sprintf(lfile, cfg_getstring(cfg, "moxa:log", NULL));
	sprintf(lfile_old, cfg_getstring(cfg, "moxa:log_old", NULL));
	bo_setLogParam(lfile, lfile_old, 0, 1000);

	/** Генерация таблицы для расчета контрольной суммы
	 * кадра сети RS485 по алгоритму CRC16-MODBUS */
	gen_tbl_crc16modbus();
	
	/** Установка таймеров */
	tscan = cfg_getint(cfg, "moxa:Tscan", -1);
	tout = cfg_getint(cfg, "moxa:Tout", -1);
	nretries = cfg_getint(cfg, "moxa:nRetries", -1);
	
	/** Установка параметров WatchDog */
	wdt_targ.tsec = cfg_getint(cfg, "WDT:Tsec", -1);
	wdt_targ.tusec = cfg_getint(cfg, "WDT:Tusec", -1);
	wdt_tm = (unsigned long)cfg_getint(cfg, "WDT:Tms", -1);
	wdt_en = cfg_getint(cfg, "WDT:enable", -1);
	/** Инициализация файла для контроля жизни программы через CRON */
	sprintf(lifeFile, cfg_getstring(cfg, "WDT:lifeFile", NULL));
	/* gen_moxa_cron_life(lifeFile); */

	/** IP адрес узла */
	sprintf(ip, cfg_getstring(cfg, "eth0:ip", NULL));

	/** FIFO сервер */
	fifo_port = (unsigned int)cfg_getint(cfg, "FIFO:port", -1);
	fifoSrv_targ.qu_len = cfg_getint(cfg, "FIFO:queue_len", -1);
	fifoSrv_targ.len = cfg_getint(cfg, "FIFO:len", -1);

	/** RT SEND server IP, port */
	sprintf(rt_ipSend, cfg_getstring(cfg, "RT:sendIp", NULL));
	rt_portSend = (unsigned int)cfg_getint(cfg, "RT:sendPort", -1);
	
	/** RT RECV server IP, port */
	sprintf(rt_ipRecv, cfg_getstring(cfg, "RT:recvIp", NULL));
	rt_portRecv = (unsigned int)cfg_getint(cfg, "RT:recvPort", -1);

	/** LOGGER server IP, port, максимальное количество строк */
	sprintf(logSend_ip, cfg_getstring(cfg, "LOGGER:sendIp", NULL));
	logSend_port = (unsigned int)cfg_getint(cfg, "LOGGER:sendPort", -1);
	logMaxLines = (unsigned int)cfg_getint(cfg, "LOGGER:maxLines", -1);
	
	/** SNMP */
	snmp_n = cfg_getint(cfg, "SNMP:n", -1);
	/** Адрес УСО */
	snmp_uso = cfg_getint(cfg, "SNMP:uso", -1);
	if (snmp_n > 0 && snmp_n <= SNMP_IP_MAX)
		for (i=0; i<snmp_n; i++) {
			sprintf(key, "SNMP:%01d", i+1);
			snmpSrv_targ.ip[i] = malloc(sizeof(char) * 16);
			tempip = cfg_getstring(cfg, key, NULL);
			memcpy(*(snmpSrv_targ.ip+i), tempip, strlen(tempip)+1);
		}
	
	/** Загрузка параметров серийного порта */
	/** 0: none, 1: odd, 2: even, 3: space, 4: mark */
	rs_parity = cfg_getint(cfg, "RS:prmParity", -1);
	/** 5 .. 8 */
	rs_databits = cfg_getint(cfg, "RS:prmDatabits", -1);
	/** 1, 2 */
	rs_stopbit = cfg_getint(cfg, "RS:prmStopbit", -1);
	/** Скорость канала RS485 */
	rs_speed = cfg_getint(cfg, "RS:speed", -1);
	
	/** Длительность одного бита (в микросекундах)
	    вычисляется по формуле: T= 1000000 / V, где V -
	    скорость передачи в бодах. Например, для
	    скорости 19200 бод длительность одного
	    бита составляет 1000000/19200= 52 мкс.
	*/
	/** коэффициент для задержки на время передачи по серийному каналу */
	utxdel = 1000000 / rs_speed * 10;
	
	/** Главная подсистема ЛС 'General' */
	sprintf(ls_gen, cfg_getstring(cfg, "LS:gen", NULL));
	cdDest = mfnv1a(ls_gen);
	
	/** Разрешение на выдачу данных 'AccessGranted' */
	sprintf(req_ag, cfg_getstring(cfg, "REQ:ag", NULL));
	cdaId = mfnv1a(req_ag);
	
	/** Состояние сети RS485 */
	sprintf(req_ns, cfg_getstring(cfg, "REQ:ns", NULL));
	cdnsId = mfnv1a(req_ns);
	
	/** Запрос лога */
	sprintf(req_gl, cfg_getstring(cfg, "REQ:gl", NULL));
	cdquLogId = mfnv1a(req_gl);
	
	/** Состояние магистрали */
	sprintf(req_ms, cfg_getstring(cfg, "REQ:ms", NULL));
	cdmsId = mfnv1a(req_ms);
	
	/** Установка параметров и открытие порта 1 RS485 */
	ch1_targ.port = cfg_getint(cfg, "RS485_1:port", -1) - 1;
	ch1_targ.src = cfg_getint(cfg, "RS485_1:adr", -1);
	ch1_targ.dst_beg = cfg_getint(cfg, "RS485_1:dstBeg", -1);
	ch1_targ.dst_end = cfg_getint(cfg, "RS485_1:dstEnd", -1);
	ch1_enable = cfg_getint(cfg, "RS485_1:enable", -1);
	
	if (ch1_enable) {
		SerialSetParam(ch1_targ.port, rs_parity, rs_databits, rs_stopbit);
		SerialOpen(ch1_targ.port);
		SerialSetSpeed(ch1_targ.port, rs_speed);
		printf("Open port%d, speed= %d\n", ch1_targ.port+1, rs_speed);
	} else
		printf("Port1 disabled\n");
	
	/** Установка параметров и открытие порта 2 RS485 */
	ch2_targ.port = cfg_getint(cfg, "RS485_2:port", -1) - 1;
	ch2_targ.src = cfg_getint(cfg, "RS485_2:adr", -1);
	ch2_targ.dst_beg = cfg_getint(cfg, "RS485_2:dstBeg", -1);
	ch2_targ.dst_end = cfg_getint(cfg, "RS485_2:dstEnd", -1);
	ch2_enable = cfg_getint(cfg, "RS485_2:enable", -1);

	if (ch2_enable) {
		SerialSetParam(ch2_targ.port, rs_parity, rs_databits, rs_stopbit);
		SerialOpen(ch2_targ.port);
		SerialSetSpeed(ch2_targ.port, rs_speed);
		printf("Open port%d, speed2= %d\n", ch2_targ.port+1, rs_speed);
	} else
		printf("Port2 disabled\n");

	cfg_free(cfg);


	/** Выделение памяти под буфер для глобальной таблицы
	 * маршрутов загружаемой с контроллера master */
	rtBuf = (unsigned char *)malloc(BO_MAX_TAB_BUF);
	if(rtBuf == NULL) {
		bo_log("main() ERROR %s", "can't alloc mem for rtBuf");
		return 1;
	}

	bo_log("Init ok");
	printf("Init ok\n");

	
	if (bo_init_fifo_out(10) == -1) {	
		bo_log("bo_init_fifo_out() ERROR");
		return 1;
	}
	
	
	/** Установка атрибутов функционирования нитей PTHREAD:
	 * - инициализирует структуру, указываемую pattr, значениями
	     "по умолчанию";
	 * - область действия конкуренции (scope) определяет связность
	 *   потока с LWP;
	 * - отсоединенность (detachstate);
	 * - область действия блокировки PTHREAD_PROCESS_PRIVATE. */
	pthread_attr_init(&pattr);
	pthread_attr_setscope(&pattr, PTHREAD_SCOPE_SYSTEM);
	pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);

	pthread_mutex_init(&mx_psv, NULL);
	pthread_mutex_init(&mx_actFIFO, NULL);
	pthread_mutex_init(&mx_rtl, NULL);
	pthread_mutex_init(&mx_rtg, NULL);

	pthread_mutex_init(&mx_sendSocket, NULL);
	
	init_thrState(&psvdata_ready);
	init_thrState(&psvAnsdata_ready);
	init_thrState(&actFIFOdata_ready);

	init_thrRxBuf(&rxBuf);
	init_thrTxBuf(&txBuf);
	init_thrDstBuf(&dstBuf);
	
	init_thrRxBuf(&rx2Buf);
	init_thrTxBuf(&tx2Buf);
	init_thrDstBuf(&dst2Buf);

	/** Инициализация условных переменных с выделением памяти */
	pthread_cond_init(&psvdata, NULL);
	pthread_cond_init(&psvAnsdata, NULL);
	pthread_cond_init(&actFIFOdata, NULL);


	/** Таблицы маршрутов */
	rtl = ht_new(0);  /** собственный узел */	
	rtg = ht_new(0);  /** внешние узлы */
	
	rtSend_sock = 0;
	rtRecv_sock = 0;

	logSend_sock = 0;
	fifo_idx = 0;

	
	log_targ.logSend_ip = logSend_ip;
	log_targ.logSend_port = logSend_port;
	result = pthread_create(&thread_log, &pattr, &logSendSock_connect, &log_targ);
	if (result) {
		printf("th_log: result = %d: %s\n", result, strerror(errno));
		return 1;
		}

	rtRecv_targ.ip = rt_ipRecv;
	rtRecv_targ.port = rt_portRecv;
	rtRecv_targ.host_ip = ip;
	result = pthread_create(&thread_rtRecv, &pattr, &rtbl_recv, &rtRecv_targ);
	if (result) {
		printf("th_rtRecv: result = %d: %s\n", result, strerror(errno));
		return 1;
	}

	rtSend_targ.ip = rt_ipSend;
	rtSend_targ.port = rt_portSend;
	rtSend_targ.host_ip = ip;
	result = pthread_create(&thread_rtSend, &pattr, &rtbl_send, &rtSend_targ);
	if (result) {
		printf("th_rtSend: result = %d: %s\n", result, strerror(errno));
		return 1;
	}

	if (snmp_n > 0 && snmp_n <= SNMP_IP_MAX) {
		snmpSrv_targ.n = snmp_n;
	
		printf("ip=%s, n=%d\n", (snmpSrv_targ.ip[0]), snmpSrv_targ.n);
	
		result = pthread_create(&thread_snmpSrv, &pattr, &snmp_serv, &snmpSrv_targ);
		if (result) {
			printf("th_snmpSrv: result = %d: %s\n", result, strerror(errno));
			return 1;
		}

		printf("snmp start ok\n");
	}
	
	fifoSrv_targ.port = fifo_port;
	result = pthread_create(&thread_fifoSrv, &pattr, &fifo_serv, &fifoSrv_targ);
	if (result) {
		printf("th_fifoSrv: result = %d: %s\n", result, strerror(errno));
		return 1;
		}

	write(1, "fifo start ok\n", 14);
		
	sendfifo_targ.port = fifo_port;
	result = pthread_create(&thread_sendfifo, &pattr, &send_fifo, &sendfifo_targ);
	if (result) {
		printf("th_sendfifo: result = %d: %s\n", result, strerror(errno));
		return 1;
		}

	write(1, "send_fifo start ok\n", 14);
	
	ch1_targ.ch1_enable = ch1_enable;
	ch1_targ.ch2_enable = ch2_enable;
	ch1_targ.tscan = tscan;
	ch1_targ.tout = tout;
	ch1_targ.utxdel = utxdel;
	ch1_targ.wdt_en = wdt_en;
	ch1_targ.nretries = nretries;
	ch1_targ.ip = ip;
	ch1_targ.fifo_port = fifo_port;
	ch1_targ.snmp_n = snmp_n;
	ch1_targ.snmp_uso = snmp_uso;
	ch1_targ.logMaxLines = logMaxLines;
	ch1_targ.cdDest = cdDest;
	ch1_targ.cdaId = cdaId;
	ch1_targ.cdnsId = cdnsId;
	ch1_targ.cdquLogId = cdquLogId;
	ch1_targ.cdmsId = cdmsId;
	result = pthread_create(&thread_ch1, &pattr, &chan1, &ch1_targ);
	if (result) {
		printf("th_ch1: result = %d: %s\n", result, strerror(errno));
		return 1;
	}

	write(1, "ch1 start ok\n", 13);
	
	ch2_targ.ch1_enable = ch1_enable;
	ch2_targ.ch2_enable = ch2_enable;
	ch2_targ.tscan = tscan;
	ch2_targ.tout = tout;
	ch2_targ.utxdel = utxdel;
	ch2_targ.wdt_en = wdt_en;
	ch2_targ.nretries = nretries;
	ch2_targ.ip = ip;
	ch2_targ.fifo_port = fifo_port;
	ch2_targ.snmp_n = snmp_n;
	ch2_targ.snmp_uso = snmp_uso;
	ch2_targ.logMaxLines = logMaxLines;
	ch2_targ.cdDest = cdDest;
	ch2_targ.cdaId = cdaId;
	ch2_targ.cdnsId = cdnsId;
	ch2_targ.cdquLogId = cdquLogId;
	ch2_targ.cdmsId = cdmsId;
	result = pthread_create(&thread_ch2, &pattr, &chan2, &ch2_targ);
	if (result) {
		printf("th_ch2: result = %d: %s\n", result, strerror(errno));
		return 1;
	}

	write(1, "ch2 start ok\n", 13);
	
#if defined (__MOXA_TARGET__) && defined (__WDT__)
	if (wdt_en) {

		/* set watch dog timer, must be refreshed in 5ms..60s */
		wdt_fd = mxwdg_open(wdt_tm);
		if (wdt_fd < 0)
		{
			printf("fail to open the watch dog !: %d [%s]\n",
			       wdt_fd, strerror(errno));
			return 1;
		}

		init_thrWdtlife(&wdt_life);
		printf("WatchDog enabled ok\n");
	}
#endif

	wdt_targ.wdt_en = wdt_en;
	wdt_targ.lifeFile = lifeFile;
	result = pthread_create(&thread_wdt, &pattr, &wdt, &wdt_targ);
	if (result) {
		printf("th_wdt: result = %d: %s\n", result, strerror(errno));
		return 1;
		}
	
	
	/** Ожидаем завершения потоков */
	if (!pthread_equal(pthread_self(), thread_log))
		pthread_join(thread_log, NULL);

	if (!pthread_equal(pthread_self(), thread_rtRecv))
		pthread_join(thread_rtRecv, NULL);
	if (!pthread_equal(pthread_self(), thread_rtSend))
		pthread_join(thread_rtSend, NULL);

	if (snmp_n > 0 && snmp_n <= SNMP_IP_MAX)
		if (!pthread_equal(pthread_self(), thread_snmpSrv))
			pthread_join(thread_snmpSrv, NULL);

	if (!pthread_equal(pthread_self(), thread_fifoSrv))
		pthread_join(thread_fifoSrv, NULL);
	if (!pthread_equal(pthread_self(), thread_sendfifo))
		pthread_join(thread_sendfifo, NULL);

	if (!pthread_equal(pthread_self(), thread_ch1))
		pthread_join(thread_ch1, NULL);
	if (!pthread_equal(pthread_self(), thread_ch2))
		pthread_join(thread_ch2, NULL);

	if (!pthread_equal(pthread_self(), thread_wdt))
		pthread_join(thread_wdt, NULL);

	
	/** Разрушаем блокировки и условные переменные, освобождаем память. */

	pthread_mutex_destroy(&mx_psv);
	pthread_mutex_destroy(&mx_actFIFO);
	pthread_mutex_destroy(&mx_rtl);
	pthread_mutex_destroy(&mx_rtg);

	pthread_mutex_destroy(&mx_sendSocket);
	
	destroy_thrRxBuf(&rxBuf);
	destroy_thrTxBuf(&txBuf);
	destroy_thrDstBuf(&dstBuf);
	
	destroy_thrRxBuf(&rx2Buf);
	destroy_thrTxBuf(&tx2Buf);
	destroy_thrDstBuf(&dst2Buf);

	pthread_cond_destroy(&psvdata);
	pthread_cond_destroy(&psvAnsdata);
	pthread_cond_destroy(&actFIFOdata);
	
	destroy_thrState(&psvdata_ready);
	destroy_thrState(&psvAnsdata_ready);
	destroy_thrState(&actFIFOdata_ready);
	
#if defined (__MOXA_TARGET__) && defined (__WDT__)
	if (wdt_en) {
		destroy_thrWdtlife(&wdt_life);
		mxwdg_close(wdt_fd);
	}
#endif

	if(rtBuf != NULL) free(rtBuf);

	rt_free(rtl);
	rt_free(rtg);
	
	return 0;
}
Пример #30
0
int main(int argc, char **argv)
{
	struct option long_options[] = {
		// These options don't set a flag
		{"help",                      no_argument,       NULL, 'h'},
		{"alternate",                 no_argument,       NULL, 'A'},
		{"effective",                 required_argument, NULL, 'f'},
		{"duration",                  required_argument, NULL, 'd'},
		{"initial-size",              required_argument, NULL, 'i'},
		{"num-threads",               required_argument, NULL, 'n'},
		{"range",                     required_argument, NULL, 'r'},
		{"seed",                      required_argument, NULL, 's'},
		{"update-rate",               required_argument, NULL, 'u'},
		{"move-rate",                 required_argument, NULL, 'm'},
		{"snapshot-rate",             required_argument, NULL, 'a'},
		{"elasticity",                required_argument, NULL, 'x'},
		{NULL, 0, NULL, 0}
	};
	
	ht_intset_t *set;
	int i, c, size;
	val_t last = 0; 
	val_t val = 0;
	unsigned long reads, effreads, updates, effupds, moves, snapshots, aborts, 
	aborts_locked_read, aborts_locked_write, aborts_validate_read, 
	aborts_validate_write, aborts_validate_commit, aborts_invalid_memory, 
	aborts_double_write,
	max_retries, failures_because_contention;
	thread_data_t *data;
	pthread_t *threads;
	pthread_attr_t attr;
	barrier_t barrier;
	struct timeval start, end;
	struct timespec timeout;
	int duration = DEFAULT_DURATION;
	int initial = DEFAULT_INITIAL;
	int nb_threads = DEFAULT_NB_THREADS;
	long range = DEFAULT_RANGE;
	int seed = DEFAULT_SEED;
	int update = DEFAULT_UPDATE;
	int load_factor = DEFAULT_LOAD;
	int move = DEFAULT_MOVE;
	int snapshot = DEFAULT_SNAPSHOT;
	int unit_tx = DEFAULT_ELASTICITY;
	int alternate = DEFAULT_ALTERNATE;
	int effective = DEFAULT_EFFECTIVE;
	sigset_t block_set;
	
	while(1) {
		i = 0;
		c = getopt_long(argc, argv, "hAf:d:i:n:r:s:u:m:a:l:x:", long_options, &i);
		
		if(c == -1)
			break;
		
		if(c == 0 && long_options[i].flag == 0)
			c = long_options[i].val;
		
		switch(c) {
				case 0:
					// Flag is automatically set 
					break;
				case 'h':
					printf("intset -- STM stress test "
								 "(hash table)\n"
								 "\n"
								 "Usage:\n"
								 "  intset [options...]\n"
								 "\n"
								 "Options:\n"
								 "  -h, --help\n"
								 "        Print this message\n"
								 "  -A, --Alternate\n"
								 "        Consecutive insert/remove target the same value\n"
								 "  -f, --effective <int>\n"
								 "        update txs must effectively write (0=trial, 1=effective, default=" XSTR(DEFAULT_EFFECTIVE) ")\n"
								 "  -d, --duration <int>\n"
								 "        Test duration in milliseconds (0=infinite, default=" XSTR(DEFAULT_DURATION) ")\n"
								 "  -i, --initial-size <int>\n"
								 "        Number of elements to insert before test (default=" XSTR(DEFAULT_INITIAL) ")\n"
								 "  -n, --num-threads <int>\n"
								 "        Number of threads (default=" XSTR(DEFAULT_NB_THREADS) ")\n"
								 "  -r, --range <int>\n"
								 "        Range of integer values inserted in set (default=" XSTR(DEFAULT_RANGE) ")\n"
								 "  -s, --seed <int>\n"
								 "        RNG seed (0=time-based, default=" XSTR(DEFAULT_SEED) ")\n"
								 "  -u, --update-rate <int>\n"
								 "        Percentage of update transactions (default=" XSTR(DEFAULT_UPDATE) ")\n"
								 "  -m , --move-rate <int>\n"
								 "        Percentage of move transactions (default=" XSTR(DEFAULT_MOVE) ")\n"
								 "  -a , --snapshot-rate <int>\n"
								 "        Percentage of snapshot transactions (default=" XSTR(DEFAULT_SNAPSHOT) ")\n"
								 "  -l , --load-factor <int>\n"
								 "        Ratio of keys over buckets (default=" XSTR(DEFAULT_LOAD) ")\n"
								 "  -x, --elasticity (default=4)\n"
								 "        Use elastic transactions\n"
								 "        0 = non-protected,\n"
								 "        1 = normal transaction,\n"
								 "        2 = read elastic-tx,\n"
								 "        3 = read/add elastic-tx,\n"
								 "        4 = read/add/rem elastic-tx,\n"
								 "        5 = elastic-tx w/ optimized move.\n"
								 );
					exit(0);
				case 'A':
					alternate = 1;
					break;
				case 'f':
					effective = atoi(optarg);
					break;
				case 'd':
					duration = atoi(optarg);
					break;
				case 'i':
					initial = atoi(optarg);
					break;
				case 'n':
					nb_threads = atoi(optarg);
					break;
				case 'r':
					range = atol(optarg);
					break;
				case 's':
					seed = atoi(optarg);
					break;
				case 'u':
					update = atoi(optarg);
					break;
				case 'm':
					move = atoi(optarg);
					break;
				case 'a':
					snapshot = atoi(optarg);
					break;
				case 'l':
					load_factor = atoi(optarg);
					break;
				case 'x':
					unit_tx = atoi(optarg);
					break;
				case '?':
					printf("Use -h or --help for help\n");
					exit(0);
				default:
					exit(1);
		}
	}
	
	assert(duration >= 0);
	assert(initial >= 0);
	assert(nb_threads > 0);
	assert(range > 0 && range >= initial);
	assert(update >= 0 && update <= 100);
	assert(move >= 0 && move <= update);
	assert(snapshot >= 0 && snapshot <= (100-update));
	assert(initial < MAXHTLENGTH);
	assert(initial >= load_factor);
	
	printf("Set type     : hash table\n");
	printf("Duration     : %d\n", duration);
	printf("Initial size : %d\n", initial);
	printf("Nb threads   : %d\n", nb_threads);
	printf("Value range  : %ld\n", range);
	printf("Seed         : %d\n", seed);
	printf("Update rate  : %d\n", update);
	printf("Load factor  : %d\n", load_factor);
	printf("Move rate    : %d\n", move);
	printf("Snapshot rate: %d\n", snapshot);
	printf("Elasticity   : %d\n", unit_tx);
	printf("Alternate    : %d\n", alternate);	
	printf("Effective    : %d\n", effective);
	printf("Type sizes   : int=%d/long=%d/ptr=%d/word=%d\n",
				 (int)sizeof(int),
				 (int)sizeof(long),
				 (int)sizeof(void *),
				 (int)sizeof(uintptr_t));
	
	timeout.tv_sec = duration / 1000;
	timeout.tv_nsec = (duration % 1000) * 1000000;
	
	if ((data = (thread_data_t *)malloc(nb_threads * sizeof(thread_data_t))) == NULL) {
		perror("malloc");
		exit(1);
	}
	if ((threads = (pthread_t *)malloc(nb_threads * sizeof(pthread_t))) == NULL) {
		perror("malloc");
		exit(1);
	}
	
	if (seed == 0)
		srand((int)time(0));
	else
		srand(seed);
	
	//maxhtlength = (unsigned int) initial / load_factor;
	set = ht_new();
	
	stop = 0;
	
	// Init STM 
	printf("Initializing STM\n");
	
	TM_STARTUP();
	
	// Populate set 
	printf("Adding %d entries to set\n", initial);
	i = 0;
	maxhtlength = (int) (initial / load_factor);
	while (i < initial) {
		val = rand_range(range);
		if (ht_add(set, val, 0)) {
		  last = val;
		  i++;			
		}
	}
	size = ht_size(set);
	printf("Set size     : %d\n", size);
	printf("Bucket amount: %d\n", maxhtlength);
	printf("Load         : %d\n", load_factor);
	
	// Access set from all threads 
	barrier_init(&barrier, nb_threads + 1);
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	for (i = 0; i < nb_threads; i++) {
		printf("Creating thread %d\n", i);
		data[i].first = last;
		data[i].range = range;
		data[i].update = update;
		data[i].load_factor = load_factor;
		data[i].move = move;
		data[i].snapshot = snapshot;
		data[i].unit_tx = unit_tx;
		data[i].alternate = alternate;
		data[i].effective = effective;
		data[i].nb_add = 0;
		data[i].nb_added = 0;
		data[i].nb_remove = 0;
		data[i].nb_removed = 0;
		data[i].nb_move = 0;
		data[i].nb_moved = 0;
		data[i].nb_snapshot = 0;
		data[i].nb_snapshoted = 0;
		data[i].nb_contains = 0;
		data[i].nb_found = 0;
		data[i].nb_aborts = 0;
		data[i].nb_aborts_locked_read = 0;
		data[i].nb_aborts_locked_write = 0;
		data[i].nb_aborts_validate_read = 0;
		data[i].nb_aborts_validate_write = 0;
		data[i].nb_aborts_validate_commit = 0;
		data[i].nb_aborts_invalid_memory = 0;
		data[i].nb_aborts_double_write = 0;
		data[i].max_retries = 0;
		data[i].seed = rand();
		data[i].set = set;
		data[i].barrier = &barrier;
		data[i].failures_because_contention = 0;
		if (pthread_create(&threads[i], &attr, test, (void *)(&data[i])) != 0) {
			fprintf(stderr, "Error creating thread\n");
			exit(1);
		}
	}
	pthread_attr_destroy(&attr);
	
	// Start threads 
	barrier_cross(&barrier);
	
	printf("STARTING...\n");
	gettimeofday(&start, NULL);
	if (duration > 0) {
		nanosleep(&timeout, NULL);
	} else {
		sigemptyset(&block_set);
		sigsuspend(&block_set);
	}
	AO_store_full(&stop, 1);
	gettimeofday(&end, NULL);
	printf("STOPPING...\n");
	
	// Wait for thread completion 
	for (i = 0; i < nb_threads; i++) {
		if (pthread_join(threads[i], NULL) != 0) {
			fprintf(stderr, "Error waiting for thread completion\n");
			exit(1);
		}
	}
	duration = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
	aborts = 0;
	aborts_locked_read = 0;
	aborts_locked_write = 0;
	aborts_validate_read = 0;
	aborts_validate_write = 0;
	aborts_validate_commit = 0;
	aborts_invalid_memory = 0;
	aborts_double_write = 0;
	failures_because_contention = 0;
	reads = 0;
	effreads = 0;
	updates = 0;
	effupds = 0;
	moves = 0;
	snapshots = 0;
	max_retries = 0;
	for (i = 0; i < nb_threads; i++) {
		printf("Thread %d\n", i);
		printf("  #add        : %lu\n", data[i].nb_add);
		printf("    #added    : %lu\n", data[i].nb_added);
		printf("  #remove     : %lu\n", data[i].nb_remove);
		printf("    #removed  : %lu\n", data[i].nb_removed);
		printf("  #contains   : %lu\n", data[i].nb_contains);
		printf("  #found      : %lu\n", data[i].nb_found);
		printf("  #move       : %lu\n", data[i].nb_move);
		printf("  #moved      : %lu\n", data[i].nb_moved);
		printf("  #snapshot   : %lu\n", data[i].nb_snapshot);
		printf("  #snapshoted : %lu\n", data[i].nb_snapshoted);
		printf("  #aborts     : %lu\n", data[i].nb_aborts);
		printf("    #lock-r   : %lu\n", data[i].nb_aborts_locked_read);
		printf("    #lock-w   : %lu\n", data[i].nb_aborts_locked_write);
		printf("    #val-r    : %lu\n", data[i].nb_aborts_validate_read);
		printf("    #val-w    : %lu\n", data[i].nb_aborts_validate_write);
		printf("    #val-c    : %lu\n", data[i].nb_aborts_validate_commit);
		printf("    #inv-mem  : %lu\n", data[i].nb_aborts_invalid_memory);
		printf("    #dup-w  : %lu\n", data[i].nb_aborts_double_write);
		printf("    #failures : %lu\n", data[i].failures_because_contention);
		printf("  Max retries : %lu\n", data[i].max_retries);
		aborts += data[i].nb_aborts;
		aborts_locked_read += data[i].nb_aborts_locked_read;
		aborts_locked_write += data[i].nb_aborts_locked_write;
		aborts_validate_read += data[i].nb_aborts_validate_read;
		aborts_validate_write += data[i].nb_aborts_validate_write;
		aborts_validate_commit += data[i].nb_aborts_validate_commit;
		aborts_invalid_memory += data[i].nb_aborts_invalid_memory;
		aborts_double_write += data[i].nb_aborts_double_write;
		failures_because_contention += data[i].failures_because_contention;
		reads += (data[i].nb_contains + data[i].nb_snapshot);
		effreads += data[i].nb_contains + 
		(data[i].nb_add - data[i].nb_added) + 
		(data[i].nb_remove - data[i].nb_removed) + 
		(data[i].nb_move - data[i].nb_moved) +
		data[i].nb_snapshoted;
		updates += (data[i].nb_add + data[i].nb_remove + data[i].nb_move);
		effupds += data[i].nb_removed + data[i].nb_added + data[i].nb_moved; 
		moves += data[i].nb_move;
		snapshots += data[i].nb_snapshot;
		size += data[i].nb_added - data[i].nb_removed;
		if (max_retries < data[i].max_retries)
			max_retries = data[i].max_retries;
	}
	printf("Set size      : %d (expected: %d)\n", ht_size(set), size);
	printf("Duration      : %d (ms)\n", duration);
	printf("#txs          : %lu (%f / s)\n", reads + updates + moves + snapshots, (reads + updates + moves + snapshots) * 1000.0 / duration);
	
	printf("#read txs     : ");
	if (effective) {
		printf("%lu (%f / s)\n", effreads, effreads * 1000.0 / duration);
		printf("  #cont/snpsht: %lu (%f / s)\n", reads, reads * 1000.0 / duration);
	} else printf("%lu (%f / s)\n", reads, reads * 1000.0 / duration);
	
	printf("#eff. upd rate: %f \n", 100.0 * effupds / (effupds + effreads));
	
	printf("#update txs   : ");
	if (effective) {
		printf("%lu (%f / s)\n", effupds, effupds * 1000.0 / duration);
		printf("  #upd trials : %lu (%f / s)\n", updates, updates * 1000.0 / 
					 duration);
	} else printf("%lu (%f / s)\n", updates, updates * 1000.0 / duration);
	
	printf("#move txs     : %lu (%f / s)\n", moves, moves * 1000.0 / duration);
	printf("#snapshot txs : %lu (%f / s)\n", snapshots, snapshots * 1000.0 / duration);
	printf("#aborts       : %lu (%f / s)\n", aborts, aborts * 1000.0 / duration);
	printf("  #lock-r     : %lu (%f / s)\n", aborts_locked_read, aborts_locked_read * 1000.0 / duration);
	printf("  #lock-w     : %lu (%f / s)\n", aborts_locked_write, aborts_locked_write * 1000.0 / duration);
	printf("  #val-r      : %lu (%f / s)\n", aborts_validate_read, aborts_validate_read * 1000.0 / duration);
	printf("  #val-w      : %lu (%f / s)\n", aborts_validate_write, aborts_validate_write * 1000.0 / duration);
	printf("  #val-c      : %lu (%f / s)\n", aborts_validate_commit, aborts_validate_commit * 1000.0 / duration);
	printf("  #inv-mem    : %lu (%f / s)\n", aborts_invalid_memory, aborts_invalid_memory * 1000.0 / duration);
	printf("  #dup-w      : %lu (%f / s)\n", aborts_double_write, aborts_double_write * 1000.0 / duration);
	printf("  #failures   : %lu\n",  failures_because_contention);
	printf("Max retries   : %lu\n", max_retries);
	
	// Delete set 
	ht_delete(set);
	
	// Cleanup STM 
	TM_SHUTDOWN();
	
	free(threads);
	free(data);
	
	return 0;
}