static gboolean get_all_clocks(struct mcap_mcl *mcl, uint32_t *btclock,
				struct timespec *base_time,
				uint64_t *timestamp)
{
	int latency;
	int retry = 5;
	uint16_t btres;
	struct timespec t0;

	if (!caps(mcl))
		return FALSE;

	latency = caps(mcl)->preempt_thresh + 1;

	while (latency > caps(mcl)->preempt_thresh && --retry >= 0) {

		clock_gettime(CLK, &t0);

		if (!read_btclock(mcl, btclock, &btres))
			continue;

		clock_gettime(CLK, base_time);

		/* Tries to detect preemption between clock_gettime
		 * and read_btclock by measuring transaction time
		 */
		latency = time_us(base_time) - time_us(&t0);
	}

	*timestamp = mcap_get_timestamp(mcl, base_time);

	return TRUE;
}
示例#2
0
static int calibrate(aeEventLoop *loop, long long id, void *data) {
    thread *thread = data;

    uint64_t elapsed_ms = (time_us() - thread->start) / 1000;
    uint64_t req_per_ms = thread->requests / elapsed_ms;

    if (!req_per_ms) return CALIBRATE_DELAY_MS / 2;

    thread->rate  = (req_per_ms * SAMPLE_INTERVAL_MS) / 10;
    thread->start = time_us();
    thread->requests = 0;
    stats_reset(thread->latency);

    aeCreateTimeEvent(loop, SAMPLE_INTERVAL_MS, sample_rate, thread, NULL);

    return AE_NOMORE;
}
uint64_t mcap_get_timestamp(struct mcap_mcl *mcl,
				struct timespec *given_time)
{
	struct timespec now;
	uint64_t tmstamp;

	if (!mcl->csp)
		return MCAP_TMSTAMP_DONTSET;

	if (given_time)
		now = *given_time;
	else
		clock_gettime(CLK, &now);

	tmstamp = time_us(&now) - time_us(&mcl->csp->base_time)
		+ mcl->csp->base_tmstamp;

	return tmstamp;
}
示例#4
0
void print_at(uint8_t x, uint8_t y, uint8_t channel){
	char buff[17];
	buff[16]=0;

	uint64_t threshold=1000000ULL; //1s

	LCD_goto(x,y);
	LCD_putc(time_us()-last_updated_at[channel]<threshold ? 'v' : 'x');
	LCD_puts(itoa((int)channels[channel],buff,10));
	LCD_putc(' ');
	LCD_putc(' ');
}
示例#5
0
void midiMainLoop(void) {
      fprintf (stderr, "midiMainLoop\n");

  jack_midi_event_t input_event; 

  int timeout = 10*1000*1000+time_us(); // 10 seconds in microseconds
//int exitMainLoop = 0;
  while (!exitMainLoop) {
    jack_nframes_t nframes = jack_cycle_wait(jack_client);
    /* Get input and output buffer pointers. */
    void* input_buf = jack_port_get_buffer (jack_midi_input_port, nframes);
    //void* output_buf = jack_port_get_buffer (jack_midi_output_port, nframes);

    jack_nframes_t input_event_count = jack_midi_get_event_count(input_buf);
    if (input_event_count>0) {
      unsigned int event_index = 0;
      for (;event_index<input_event_count;event_index++) {
	if (0==jack_midi_event_get(&input_event, input_buf, event_index)) {
	  if (input_event.size > 0) {

	printhex("receive:", input_event.buffer,input_event.size);

	    int i = 0;
	    for (; i < input_event.size; i++) {
	      midiReceive(input_event.buffer[i]);
	    }
	  }
        }
      }
    } 

    if (time_us() > timeout) {
        fprintf(stderr, "timeout\n");
	exit(1);
    }
  }

  jack_end();
      fprintf (stderr, "midiMainLoop:end\n");
}
示例#6
0
static void socket_writeable(aeEventLoop *loop, int fd, void *data, int mask) {
    connection *c = data;

    if (write(fd, c->hash, SHA_LENGTH * 2) < SHA_LENGTH * 2) goto error;
    c->start = time_us();
    aeDeleteFileEvent(loop, fd, AE_WRITABLE);

    return;

  error:
    c->thread->errors.write++;
    reconnect_socket(c->thread, c);
}
示例#7
0
static int sample_rate(aeEventLoop *loop, long long id, void *data) {
    thread *thread = data;

    uint64_t elapsed_ms = (time_us() - thread->start) / 1000;
    uint64_t requests = (thread->requests / elapsed_ms) * 1000;
    uint64_t missed = thread->rate - MIN(thread->rate, thread->latency->limit);
    uint64_t count = thread->rate - missed;

    pthread_mutex_lock(&statistics.mutex);
    stats_sample(statistics.latency, &thread->rand, count, thread->latency);
    stats_record(statistics.requests, requests);
    pthread_mutex_unlock(&statistics.mutex);

    uint64_t max = thread->latency->max;
    thread->missed  += missed;
    thread->requests = 0;
    thread->start    = time_us();
    stats_reset(thread->latency);
    thread->latency->max = max;

    return SAMPLE_INTERVAL_MS;
}
示例#8
0
static int check_timeouts(aeEventLoop *loop, long long id, void *data) {
    thread *thread = data;
    connection *c  = thread->cs;
    uint64_t now   = time_us();

    uint64_t maxAge = now - (cfg.timeout * 1000);

    for (uint64_t i = 0; i < thread->connections; i++, c++) {
        if (maxAge > c->start) {
            thread->errors.timeout++;
        }
    }

    if (stop || now >= thread->stop_at) {
        aeStop(loop);
    }

    return TIMEOUT_INTERVAL_MS;
}
示例#9
0
static void socket_readable(aeEventLoop *loop, int fd, void *data, int mask) {
    connection *c = data;
    thread *thread = c->thread;
    uint64_t now;
    ssize_t n;

    if ((n = read(fd, c->buf, sizeof(c->buf))) <= 0) goto error;
    c->buf[n] = '\0';

    now = time_us();
    if (!validate_response(c)) goto invalid;
    thread->bytes += n;
    thread->complete++;
    thread->requests++;

    stats_record(thread->latency, now - c->start);

    if (now >= thread->stop_at) {
        aeStop(thread->loop);
        close(c->fd);
    }
    else {
        reconnect_socket(c->thread, c);
    }

    return;

  invalid:
    c->thread->errors.validate++;
    reconnect_socket(c->thread, c);
    return;

  error:
    c->thread->errors.read++;
    reconnect_socket(c->thread, c);
}
static gboolean initialize_caps(struct mcap_mcl *mcl)
{
	struct timespec t1, t2;
	int latencies[SAMPLE_COUNT];
	int latency, avg, dev;
	uint32_t btclock;
	uint16_t btaccuracy;
	int i;
	int retries;

	clock_getres(CLK, &t1);

	_caps.ts_res = time_us(&t1);
	if (_caps.ts_res < 1)
		_caps.ts_res = 1;

	_caps.ts_acc = 20; /* ppm, estimated */

	/* A little exercise before measuing latency */
	clock_gettime(CLK, &t1);
	read_btclock_retry(mcl, &btclock, &btaccuracy);

	/* Read clock a number of times and measure latency */
	avg = 0;
	i = 0;
	retries = MAX_RETRIES;
	while (i < SAMPLE_COUNT && retries > 0) {
		clock_gettime(CLK, &t1);
		if (!read_btclock(mcl, &btclock, &btaccuracy)) {
			retries--;
			continue;
		}
		clock_gettime(CLK, &t2);

		latency = time_us(&t2) - time_us(&t1);
		latencies[i] = latency;
		avg += latency;
		i++;
	}

	if (retries <= 0)
		return FALSE;

	/* Calculate average and deviation */
	avg /= SAMPLE_COUNT;
	dev = 0;
	for (i = 0; i < SAMPLE_COUNT; ++i)
		dev += abs(latencies[i] - avg);
	dev /= SAMPLE_COUNT;

	/* Calculate corrected average, without 'freak' latencies */
	latency = 0;
	for (i = 0; i < SAMPLE_COUNT; ++i) {
		if (latencies[i] > (avg + dev * 6))
			latency += avg;
		else
			latency += latencies[i];
	}
	latency /= SAMPLE_COUNT;

	_caps.latency = latency;
	_caps.preempt_thresh = latency * 4;
	_caps.syncleadtime_ms = latency * 50 / 1000;

	csp_caps_initialized = TRUE;
	return TRUE;
}
示例#11
0
int main(int argc, char **argv) {
    struct addrinfo *addrs, *addr;
    char *host = "127.0.0.1";
    char *port = "1337";
    int rc;
    // for checking that the server's up
    char poke[SHA_LENGTH * 2];
    tinymt64_t rando;

    if (parse_args(&cfg, &host, &port, argc, argv)) {
        usage();
        exit(1);
    }

    struct addrinfo hints = {
        .ai_family   = AF_UNSPEC,
        .ai_socktype = SOCK_STREAM
    };

    if ((rc = getaddrinfo(host, port, &hints, &addrs)) != 0) {
        const char *msg = gai_strerror(rc);
        fprintf(stderr, "unable to resolve %s:%s: %s\n", host, port, msg);
        exit(1);
    }

    for (addr = addrs; addr != NULL; addr = addr->ai_next) {
        int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (fd == -1) continue;
        rc = connect(fd, addr->ai_addr, addr->ai_addrlen);
        tinymt64_init(&rando, time_us());
        random_hash(&rando, poke);
        if (rc == 0 && write(fd, poke, SHA_LENGTH * 2) == SHA_LENGTH * 2) {
            read(fd, poke, SHA_LENGTH * 2);
            close(fd);
            break;
        }
        close(fd);
    }

    if (addr == NULL) {
        char *msg = strerror(errno);
        fprintf(stderr, "unable to connect to %s:%s: %s\n", host, port, msg);
        exit(1);
    }

    signal(SIGPIPE, SIG_IGN);
    signal(SIGINT,  SIG_IGN);
    cfg.addr = *addr;

    pthread_mutex_init(&statistics.mutex, NULL);
    statistics.latency  = stats_alloc(SAMPLES);
    statistics.requests = stats_alloc(SAMPLES);

    thread *threads = zcalloc(cfg.threads * sizeof(thread));
    uint64_t connections = cfg.connections / cfg.threads;
    uint64_t stop_at     = time_us() + (cfg.duration * 1000000);

    for (uint64_t i = 0; i < cfg.threads; i++) {
        thread *t = &threads[i];
        t->connections = connections;
        t->stop_at     = stop_at;

        if (pthread_create(&t->thread, NULL, &thread_main, t)) {
            char *msg = strerror(errno);
            fprintf(stderr, "unable to create thread %"PRIu64" %s\n", i, msg);
            exit(2);
        }
    }

    struct sigaction sa = {
        .sa_handler = handler,
        .sa_flags   = 0,
    };
    sigfillset(&sa.sa_mask);
    sigaction(SIGINT, &sa, NULL);

    char *time = format_time_s(cfg.duration);
    printf("Running %s test @ %s:%s\n", time, host, port);
    printf("  %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections);

    uint64_t start    = time_us();
    uint64_t complete = 0;
    uint64_t bytes    = 0;
    errors errors     = { 0 };

    for (uint64_t i = 0; i < cfg.threads; i++) {
        thread *t = &threads[i];
        pthread_join(t->thread, NULL);

        complete += t->complete;
        bytes    += t->bytes;

        errors.connect   += t->errors.connect;
        errors.handshake += t->errors.handshake;
        errors.read      += t->errors.read;
        errors.validate  += t->errors.validate;
        errors.write     += t->errors.write;
        errors.timeout   += t->errors.timeout;
    }

    uint64_t runtime_us = time_us() - start;
    long double runtime_s   = runtime_us / 1000000.0;
    long double req_per_s   = complete   / runtime_s;
    long double bytes_per_s = bytes      / runtime_s;

    print_stats_header();
    print_stats("Latency", statistics.latency, format_time_us);
    print_stats("Req/Sec", statistics.requests, format_metric);
    if (cfg.latency) print_stats_latency(statistics.latency);

    char *runtime_msg = format_time_us(runtime_us);

    printf("  %"PRIu64" requests in %s, %sB read\n", complete, runtime_msg, format_binary(bytes));
    if (errors.connect || errors.read || errors.write || errors.timeout) {
        printf("  Socket errors: connect %d, read %d, write %d, timeout %d\n",
               errors.connect, errors.read, errors.write, errors.timeout);
    }

    if (errors.handshake) {
        printf("  Bad handshakes from server: %d\n", errors.handshake);
    }

    if (errors.validate) {
        printf("  %d proofs failed verification.\n", errors.validate);
    }

    printf("Requests/sec: %9.2Lf\n", req_per_s);
    printf("Transfer/sec: %10sB\n", format_binary(bytes_per_s));

    return 0;
}

void *thread_main(void *arg) {
    thread *thread = arg;

    aeEventLoop *loop = aeCreateEventLoop(10 + cfg.connections * 3);
    thread->cs   = zmalloc(thread->connections * sizeof(connection));
    thread->loop = loop;
    tinymt64_init(&thread->rand, time_us());
    thread->latency = stats_alloc(100000);

    connection *c = thread->cs;

    for (uint64_t i = 0; i < thread->connections; i++, c++) {
        c->thread = thread;
        random_hash(&thread->rand, c->hash);
        connect_socket(thread, c);
    }

    aeCreateTimeEvent(loop, CALIBRATE_DELAY_MS, calibrate, thread, NULL);
    aeCreateTimeEvent(loop, TIMEOUT_INTERVAL_MS, check_timeouts, thread, NULL);

    thread->start = time_us();
    aeMain(loop);

    aeDeleteEventLoop(loop);
    zfree(thread->cs);

    uint64_t max = thread->latency->max;
    stats_free(thread->latency);

    pthread_mutex_lock(&statistics.mutex);
    for (uint64_t i = 0; i < thread->missed; i++) {
        stats_record(statistics.latency, max);
    }
    pthread_mutex_unlock(&statistics.mutex);

    return NULL;
}