Exemplo n.º 1
0
int sick_transaction(sick_t *s, uint8_t *request, uint8_t responsetype, uint8_t *response, int timeoutms)
{
    pthread_mutex_lock(&s->writelock);

    int res = 0;
    int trials = 0;
    int requestlen;

retry:
    requestlen = packet_length(request);

    if (s->log_packets_file) {
        for (int i = 0; i < requestlen; i++) {
            if (i%16 == 0)
                fprintf(s->log_packets_file, "TX %04x : ", i);
            fprintf(s->log_packets_file, "%02x ", request[i]);
            if ((i%16) == 15 || i+1 == requestlen)
                fprintf(s->log_packets_file, "\n");
        }
    }

    // send the request
    res = write_fully(s->serialfd, request, requestlen);

    if (res < 0) {
        printf("write failed\n");
        goto exit;
    }

    // wait for response
    s->writereqid = responsetype;
    s->writedata = response;
    s->writevalid = 0;

    struct timespec ts;
    timespec_now(&ts);
    timespec_addms(&ts, timeoutms);

    pthread_cond_timedwait(&s->writecond, &s->writelock, &ts);

    if (!s->writevalid) {
        trials++;
        if (trials > SICK_OP_MAX_RETRIES) {
            res = -2;
            goto exit;
        }
        goto retry;
    }

exit:
    s->writedata = NULL;
    s->writereqid = 0;

    pthread_mutex_unlock(&s->writelock);

    return res;
}
Exemplo n.º 2
0
rpc_ctx_t *
alloc_rpc_call_ctx(CLIENT *clnt, rpcproc_t proc, xdrproc_t xdr_args,
                   void *args_ptr, xdrproc_t xdr_results, void *results_ptr,
                   struct timeval timeout)
{
    struct x_vc_data *xd = (struct x_vc_data *) clnt->cl_p1;
    struct rpc_dplx_rec *rec = xd->rec;
    rpc_ctx_t *ctx;

    ctx = mem_alloc(sizeof(rpc_ctx_t));
    if (! ctx)
        goto out;

    /* potects this */
    mutex_init(&ctx->we.mtx, NULL);
    cond_init(&ctx->we.cv, 0, NULL);

    /* rec->calls and rbtree protected by (adaptive) mtx */
    mutex_lock(&rec->mtx);

    /* XXX we hold the client-fd lock */
    ctx->xid = ++(xd->cx.calls.xid);

    /* some of this looks like overkill;  it's here to support future,
     * fully async calls */
    ctx->ctx_u.clnt.clnt = clnt;
    ctx->ctx_u.clnt.timeout.tv_sec = 0;
    ctx->ctx_u.clnt.timeout.tv_nsec = 0;
    timespec_addms(&ctx->ctx_u.clnt.timeout, tv_to_ms(&timeout));
    ctx->msg = alloc_rpc_msg();
    ctx->flags = 0;

    /* stash it */
    if (opr_rbtree_insert(&xd->cx.calls.t, &ctx->node_k)) {
        __warnx(TIRPC_DEBUG_FLAG_RPC_CTX,
                "%s: call ctx insert failed (xid %d client %p)",
                __func__,
                ctx->xid, clnt);
        mutex_unlock(&rec->mtx);
        mem_free(ctx, sizeof(rpc_ctx_t));
        ctx = NULL;
        goto out;
    }

    mutex_unlock(&rec->mtx);

out:
    return (ctx);
}
Exemplo n.º 3
0
int orc_transaction_once(orc_t *orc, uint8_t *request, uint8_t *response)
{
	while (orc->fd <= 0) {
		usleep(1000);
	}
	
	// grab an id
	int id = alloc_transaction_id(orc);

	// fix up the packet.
	request[0] = PACKET_MARKER;
	request[PACKET_ID] = id;
	packet_fill_checksum(request);

	// fill out the transaction record
	transaction_t *t = &orc->transactions[id];
	pthread_mutex_lock(&t->mutex);
	t->response = response;

	// send the packet
	pthread_mutex_lock(&orc->writeLock);
	write_fully(orc->fd, request, request[PACKET_DATALEN] + 4);
	pthread_mutex_unlock(&orc->writeLock);

	// compute our timeout time
	struct timespec ts;
	timespec_now(&ts);
	timespec_addms(&ts, 100);
	
	// wait!
	int res = pthread_cond_timedwait(&t->cond, &t->mutex, &ts);

	t->response = garbage;
	
	// cleanup
	pthread_mutex_unlock(&t->mutex);
	free_transaction_id(orc, id);

	if (res == ETIMEDOUT) {
		LOG_VERBOSE("Timeout packet, id = %02X", id);
		return -1;
	}

	return 0;
}