예제 #1
0
static void *
test(void *c)
{
#ifdef CK_F_FIFO_MPMC
	struct context *context = c;
	struct entry *entry;
	ck_fifo_mpmc_entry_t *fifo_entry, *garbage;
	int i, j;

        if (aff_iterate(&a)) {
                perror("ERROR: Could not affine thread");
                exit(EXIT_FAILURE);
        }

	ck_pr_inc_uint(&barrier);
	while (ck_pr_load_uint(&barrier) < (unsigned int)nthr);

	for (i = 0; i < ITERATIONS; i++) {
		for (j = 0; j < size; j++) {
			fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t));
			entry = malloc(sizeof(struct entry));
			entry->tid = context->tid;
			ck_fifo_mpmc_enqueue(&fifo, fifo_entry, entry);
			if (ck_fifo_mpmc_dequeue(&fifo, &entry, &garbage) == false) {
				fprintf(stderr, "ERROR [%u] Queue should never be empty.\n", context->tid);
				exit(EXIT_FAILURE);
			}

			if (entry->tid < 0 || entry->tid >= nthr) {
				fprintf(stderr, "ERROR [%u] Incorrect value in entry.\n", entry->tid);
				exit(EXIT_FAILURE);
			}
		}
	}

	for (i = 0; i < ITERATIONS; i++) {
		for (j = 0; j < size; j++) {
			fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t));
			entry = malloc(sizeof(struct entry));
			entry->tid = context->tid;
			while (ck_fifo_mpmc_tryenqueue(&fifo, fifo_entry, entry) == false)
				ck_pr_stall();

			while (ck_fifo_mpmc_trydequeue(&fifo, &entry, &garbage) == false)
				ck_pr_stall();

			if (entry->tid < 0 || entry->tid >= nthr) {
				fprintf(stderr, "ERROR [%u] Incorrect value in entry when using try interface.\n", entry->tid);
				exit(EXIT_FAILURE);
			}
		}
	}
#endif

	return (NULL);
}
예제 #2
0
파일: fq_client.c 프로젝트: retailnext/fq
fq_msg *fq_client_receive(fq_client conn) {
  fq_conn_s *conn_s = conn;
  fq_msg *m = NULL;
  ck_fifo_mpmc_entry_t *garbage;

  if(ck_fifo_mpmc_dequeue(&conn_s->backq, &m, &garbage) == true) {
    free(garbage);
  }
  return m;
}
예제 #3
0
파일: latency.c 프로젝트: Sphonic/fq
int
main(void)
{
	ck_spinlock_fas_t mutex = CK_SPINLOCK_FAS_INITIALIZER;
	void *r;
	uint64_t s, e, a;
	unsigned int i;
	unsigned int j;

#if   defined(CK_F_FIFO_SPSC)
	ck_fifo_spsc_t spsc_fifo;
	ck_fifo_spsc_entry_t spsc_entry[ENTRIES];
	ck_fifo_spsc_entry_t spsc_stub;
#endif

#if defined(CK_F_FIFO_MPMC)
	ck_fifo_mpmc_t mpmc_fifo;
	ck_fifo_mpmc_entry_t mpmc_entry[ENTRIES];
	ck_fifo_mpmc_entry_t mpmc_stub;
	ck_fifo_mpmc_entry_t *garbage;
#endif

#ifdef CK_F_FIFO_SPSC
	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++) {
			ck_spinlock_fas_lock(&mutex);
			ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
			ck_spinlock_fas_unlock(&mutex);
		}
		e = rdtsc();

		a += e - s;
	}
	printf("    spinlock_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));

	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++) {
			ck_spinlock_fas_lock(&mutex);
			ck_fifo_spsc_dequeue(&spsc_fifo, &r);
			ck_spinlock_fas_unlock(&mutex);
		}
		e = rdtsc();
		a += e - s;
	}
	printf("    spinlock_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));

	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);
		e = rdtsc();

		a += e - s;
	}
	printf("ck_fifo_spsc_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));

	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_spsc_init(&spsc_fifo, &spsc_stub);
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_spsc_enqueue(&spsc_fifo, spsc_entry + j, NULL);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_spsc_dequeue(&spsc_fifo, &r);
		e = rdtsc();
		a += e - s;
	}
	printf("ck_fifo_spsc_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(spsc_entry) / sizeof(*spsc_entry)));
#endif

#ifdef CK_F_FIFO_MPMC
	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_mpmc_init(&mpmc_fifo, &mpmc_stub);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_mpmc_enqueue(&mpmc_fifo, mpmc_entry + j, NULL);
		e = rdtsc();

		a += e - s;
	}
	printf("ck_fifo_mpmc_enqueue: %16" PRIu64 "\n", a / STEPS / (sizeof(mpmc_entry) / sizeof(*mpmc_entry)));

	a = 0;
	for (i = 0; i < STEPS; i++) {
		ck_fifo_mpmc_init(&mpmc_fifo, &mpmc_stub);
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_mpmc_enqueue(&mpmc_fifo, mpmc_entry + j, NULL);

		s = rdtsc();
		for (j = 0; j < ENTRIES; j++)
			ck_fifo_mpmc_dequeue(&mpmc_fifo, &r, &garbage);
		e = rdtsc();
		a += e - s;
	}
	printf("ck_fifo_mpmc_dequeue: %16" PRIu64 "\n", a / STEPS / (sizeof(mpmc_entry) / sizeof(*mpmc_entry)));
#endif

	return 0;
}
예제 #4
0
파일: fq_client.c 프로젝트: retailnext/fq
static void *
fq_conn_worker(void *u) {
  int backoff = 0;
  fq_conn_s *conn_s = (fq_conn_s *)u;
  cmd_instr *last_entry = NULL;
  uint16_t expect;
  while(conn_s->stop == 0) {
   restart:
    expect = 0;
    if(fq_client_connect_internal(conn_s) == 0) {
      backoff = 0; /* we're good, restart our backoff */
    }

    while(conn_s->data_ready) {
      hrtime_t t;
      unsigned long long hb_us;
      struct timeval tv;
      int rv;
      cmd_instr *entry;
      ck_fifo_mpmc_entry_t *garbage;

      while(ck_fifo_mpmc_dequeue(&conn_s->cmdq, &entry, &garbage) == true) {
        free(garbage);
#ifdef DEBUG
        fq_debug(FQ_DEBUG_CONN, "client acting on user req 0x%04x\n", entry->cmd);
#endif
        switch(entry->cmd) {
          case FQ_PROTO_STATUSREQ:
            if(expect != 0) {
              if(conn_s->errorlog) conn_s->errorlog("protocol violation");
              goto restart;
            }
            fq_debug(FQ_DEBUG_CONN, "sending status request\n");
            if(fq_write_uint16(conn_s->cmd_fd, entry->cmd)) {
              free(entry);
              goto restart;
            }
            expect = FQ_PROTO_STATUS;
            last_entry = entry;
            break;
          case FQ_PROTO_HBREQ:
            fq_debug(FQ_DEBUG_CONN, "sending heartbeat request\n");
            if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) ||
               fq_write_uint16(conn_s->cmd_fd, entry->data.heartbeat.ms)) {
              free(entry);
              goto restart;
            }
            conn_s->cmd_hb_ms = entry->data.heartbeat.ms;
            tv.tv_sec = (unsigned long)entry->data.heartbeat.ms / 1000;
            tv.tv_usec = 1000UL * (entry->data.heartbeat.ms % 1000);
            if(setsockopt(conn_s->cmd_fd, SOL_SOCKET, SO_RCVTIMEO,
                          &tv, sizeof(tv)))
              CONNERR(conn_s, strerror(errno));
            tv.tv_sec = (unsigned long)entry->data.heartbeat.ms / 1000;
            tv.tv_usec = 1000UL * (entry->data.heartbeat.ms % 1000);
            if(setsockopt(conn_s->cmd_fd, SOL_SOCKET, SO_SNDTIMEO,
                          &tv, sizeof(tv)))
              CONNERR(conn_s, strerror(errno));
            conn_s->cmd_hb_last = fq_gethrtime();
            free(entry);
            break;
          case FQ_PROTO_BINDREQ:
            {
              unsigned short peermode = entry->data.bind->peermode ? 1 : 0;
              if(expect != 0) {
                if(conn_s->errorlog) conn_s->errorlog("protocol violation");
                goto restart;
              }
              if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) ||
                 fq_write_uint16(conn_s->cmd_fd, peermode) ||
                 fq_write_short_cmd(conn_s->cmd_fd,
                                    entry->data.bind->exchange.len,
                                    entry->data.bind->exchange.name) < 0 ||
                 fq_write_short_cmd(conn_s->cmd_fd,
                                    strlen(entry->data.bind->program),
                                    entry->data.bind->program) < 0) {
                goto restart;
              }
              expect = FQ_PROTO_BIND;
              last_entry = entry;
            }
            break;
          case FQ_PROTO_UNBINDREQ:
            {
              if(expect != 0) {
                if(conn_s->errorlog) conn_s->errorlog("protocol violation");
                goto restart;
              }
              if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) ||
                 fq_write_uint32(conn_s->cmd_fd, entry->data.unbind->route_id) ||
                 fq_write_short_cmd(conn_s->cmd_fd,
                                    entry->data.unbind->exchange.len,
                                    entry->data.unbind->exchange.name) < 0) {
                goto restart;
              }
              expect = FQ_PROTO_UNBIND;
              last_entry = entry;
            }
            break;
          default:
            if(conn_s->errorlog) conn_s->errorlog("unknown user-side cmd");
            free(entry);
        }
      }

      if(conn_s->cmd_hb_needed) {
#ifdef DEBUG
          fq_debug(FQ_DEBUG_CONN, "-> heartbeat\n");
#endif
        if(fq_write_uint16(conn_s->cmd_fd, FQ_PROTO_HB)) break;
        conn_s->cmd_hb_needed = 0;
      }

      rv = fq_client_wfrw_internal(conn_s->cmd_fd, 1, 0, 50, NULL);
      t = fq_gethrtime();
      hb_us = (unsigned long long)conn_s->cmd_hb_ms * 3 * 1000000ULL;
      if(conn_s->cmd_hb_last && hb_us &&
         conn_s->cmd_hb_last < (unsigned int) (t - hb_us)) {
        char errbuf[256];
        snprintf(errbuf, sizeof(errbuf), "heartbeat failed [%llu - %llu = %llu]",
                 (unsigned long long)t, (unsigned long long)conn_s->cmd_hb_last,
                 (unsigned long long)(t - conn_s->cmd_hb_last));
        CONNERR(conn_s, errbuf);
        break;
      }
      if(rv < 0) {
        CONNERR(conn_s, strerror(errno));
        break;
      }
      if(rv > 0) {
        uint16_t hb;
        if(fq_read_uint16(conn_s->cmd_fd, &hb)) break;
        switch(hb) {
          case FQ_PROTO_HB:
#ifdef DEBUG
            fq_debug(FQ_DEBUG_CONN, "<- heartbeat\n");
#endif
            conn_s->cmd_hb_last = fq_gethrtime();
            conn_s->cmd_hb_needed = 1;
            break;
          case FQ_PROTO_STATUS:
            if(expect != FQ_PROTO_STATUS) {
              if(conn_s->errorlog) conn_s->errorlog("protocol violation");
              goto restart;
            }
            if(fq_read_status(conn_s->cmd_fd,
                              last_entry->data.status.callback,
                              last_entry->data.status.closure))
              goto restart;
            expect = 0;
            break;
          case FQ_PROTO_BIND:
            if(expect != FQ_PROTO_BIND) {
              if(conn_s->errorlog) conn_s->errorlog("protocol violation");
              goto restart;
            }
            if(fq_read_uint32(conn_s->cmd_fd,
                              &last_entry->data.bind->out__route_id))
              goto restart;
            expect = 0;
            break;
          case FQ_PROTO_UNBIND:
            if(expect != FQ_PROTO_UNBIND) {
              if(conn_s->errorlog) conn_s->errorlog("protocol violation");
              goto restart;
            }
            if(fq_read_uint32(conn_s->cmd_fd,
                              &last_entry->data.unbind->out__success))
              goto restart;
            expect = 0;
            break;
          default:
            if(conn_s->errorlog) conn_s->errorlog("protocol violation");
            goto restart;
            break;
        }
      }
    }

#ifdef DEBUG
    fq_debug(FQ_DEBUG_CONN, "[cmd] connection failed: %s\n", conn_s->error);
#endif
    usleep(backoff);
    backoff += 10000;
  }
  fq_client_disconnect_internal(conn_s);
  return (void *)NULL;
}
예제 #5
0
파일: fq_client.c 프로젝트: retailnext/fq
static void
fq_data_worker_loop(fq_conn_s *conn_s) {
  buffered_msg_reader *ctx = NULL;
  ctx = fq_buffered_msg_reader_alloc(conn_s->data_fd, 1);
  while(conn_s->cmd_fd >= 0 && conn_s->stop == 0) {
    int rv;
    int wait_ms = 500, needs_write = 0, mask, write_rv;
    ck_fifo_mpmc_entry_t *garbage;
    if(conn_s->tosend) goto the_thick_of_it;
    while(ck_fifo_mpmc_dequeue(&conn_s->q, &conn_s->tosend, &garbage) == true) {
      conn_s->tosend_offset = 0;
      ck_pr_dec_uint(&conn_s->qlen);
      free(garbage);
     the_thick_of_it:
#ifdef DEBUG
      fq_debug(FQ_DEBUG_MSG, "dequeue message to submit to server\n");
#endif
      write_rv = fq_client_write_msg(conn_s->data_fd, conn_s->peermode,
                                     conn_s->tosend, conn_s->tosend_offset);
      if(write_rv > 0) {
        conn_s->tosend_offset += write_rv;
        break;
      }
      if(write_rv < 0) {
        if(errno == EAGAIN) {
          needs_write = 1;
          break;
        }
        if(conn_s->errorlog) {
          char errbuf[128];
          snprintf(errbuf, sizeof(errbuf), "data write error: %s\n", strerror(errno));
          conn_s->errorlog(errbuf);
        }
        goto finish;
      }
      fq_msg_deref(conn_s->tosend);
      conn_s->tosend = NULL;
      conn_s->tosend_offset = 0;
      wait_ms = 0;
    }
    rv = fq_client_wfrw_internal(conn_s->data_fd, 1, needs_write, wait_ms, &mask);
    if(rv < 0) {
      if(conn_s->errorlog) {
        char errbuf[128];
        snprintf(errbuf, sizeof(errbuf), "data read error: %s\n", strerror(errno));
        conn_s->errorlog(errbuf);
      }
      goto finish;
    }
    if(rv > 0 && (mask & POLLIN)) {
      if(fq_buffered_msg_read(ctx, fq_client_read_complete, conn_s) < 0) {
        if(conn_s->errorlog) conn_s->errorlog("data read: end-of-line\n");
        goto finish;
      }
    }
  }
finish:
  if(ctx) fq_buffered_msg_reader_free(ctx);
#ifdef DEBUG
  fq_debug(FQ_DEBUG_CONN, "cmd_fd -> %d, stop -> %d\n", conn_s->cmd_fd, conn_s->stop);
#endif
}