Exemple #1
0
static void process(ErlDrvData handle, ErlIOVec *ev) {
  spidermonkey_drv_t *dd = (spidermonkey_drv_t *) handle;
  char *data = ev->binv[1]->orig_bytes;
  char *command = read_command(&data);
  if (strncmp(command, "ij", 2) == 0) {
    char *call_id = read_string(&data);
    int thread_stack = read_int32(&data);
    if (thread_stack < 8) {
      thread_stack = 8;
    }
    thread_stack = thread_stack * (1024 * 1024);
    int heap_size = read_int32(&data) * (1024 * 1024);
    dd->vm = sm_initialize(thread_stack, heap_size);
    send_ok_response(dd, call_id);
    driver_free(call_id);
  }
  else {
    js_call *call_data = (js_call *) driver_alloc(sizeof(js_call));
    call_data->driver_data = dd;
    call_data->args = ev->binv[1];
    driver_binary_inc_refc(call_data->args);
    ErlDrvPort port = dd->port;
    unsigned long thread_key = (unsigned long) port;
    driver_async(dd->port, (unsigned int *) &thread_key, (asyncfun) run_js, (void *) call_data, NULL);
  }
  driver_free(command);
}
Exemple #2
0
static void
standard_outputv(ErlDrvData drv_data, ErlIOVec* ev)
{
   wxe_data* sd = (wxe_data *) drv_data;
   WXEBinRef * binref;
   ErlDrvBinary* bin;
   
   if(ev->vsize == 2) {
      binref = driver_alloc(sizeof(WXEBinRef));
      binref->base = ev->iov[1].iov_base;
      binref->size = ev->iov[1].iov_len;
      binref->from = driver_caller(sd->port);
      bin = ev->binv[1];
      driver_binary_inc_refc(bin); /* Otherwise it could get deallocated */
      binref->bin = bin;
      binref->next = sd->bin;
      sd->bin = binref;      
   } else { /* Empty binary (becomes NULL) */ 
      binref = driver_alloc(sizeof(WXEBinRef));
      binref->base = NULL;
      binref->size = 0;
      binref->from = driver_caller(sd->port);
      binref->bin = NULL;
      binref->next = sd->bin;
      sd->bin = binref;
   }
}
Exemple #3
0
static void av_decoder_schedule_decode(ErlDrvData drv_data, ErlIOVec *ev)
{
  H264Decoder* d = (H264Decoder*)drv_data;
  //  av_log(d->dec,AV_LOG_WARNING,"\nVSIZE:: %i\n");
  ErlDrvBinary *h264 = NULL;
  int i;
  for(i = 0; i < ev->vsize; i++) {
    if(h264 && ev->binv[i]) {
      driver_failure_atom(d->port, "invalid_output_vector");
      return;
    }
    if(ev->binv[i]) h264 = ev->binv[i];
  }
  if(!h264) {
    driver_failure_atom(d->port, "invalid_output_vector");
    return;
  }
  H264Frame *frame = driver_alloc(sizeof(H264Frame));
  bzero(frame, sizeof(H264Frame));
  frame->h264 = h264;
  // av_log(NULL,AV_LOG_INFO,"Size:: %i ",h264->orig_size);
  frame->decoder = d;
  driver_binary_inc_refc(h264);
  // I must change driver_free for other, more clever clearer, because yuv field must be also freed.
  driver_async(d->port, &d->key, av_async_decode, frame, driver_free);
}
Exemple #4
0
/* Put elements from vec at q head */
int erts_ioq_pushqv(ErtsIOQueue *q, ErtsIOVec* vec, Uint skipbytes)
{
    int n;
    Uint len;
    Uint size = vec->common.size - skipbytes;
    SysIOVec* iov;
    ErtsIOQBinary** binv;
    ErtsIOQBinary* b;

    if (q == NULL)
	return -1;

    ASSERT(vec->common.size >= skipbytes);
    if (vec->common.size <= skipbytes)
	return 0;

    n = skip(vec, skipbytes, &iov, &binv, &len);

    if (n < 0)
        return n;

    if (q->v_head - n < q->v_start)
	if (expandq(q, n, 0))
            return -1;

    /* Queue and reference all binaries (remove zero length items) */
    iov += (n-1);  /* move to end */
    binv += (n-1); /* move to end */
    while(n--) {
	if ((len = iov->iov_len) > 0) {
	    if ((b = *binv) == NULL) { /* special case create binary ! */
                if (q->driver) {
                    ErlDrvBinary *bin = driver_alloc_binary(len);
                    if (!bin) return -1;
                    sys_memcpy(bin->orig_bytes, iov->iov_base, len);
                    b = (ErtsIOQBinary *)bin;
                    q->v_head->iov_base = bin->orig_bytes;
                }
		*--q->b_head = b;
		q->v_head--;
		q->v_head->iov_len = len;
	    }
	    else {
                if (q->driver)
                    driver_binary_inc_refc(&b->driver);
                else
                    erts_refc_inc(&b->nif.intern.refc, 1);
		*--q->b_head = b;
		*--q->v_head = *iov;
	    }
	}
	iov--;
	binv--;
    }
    q->size += size;      /* update total size in queue */
    return 0;
}
Exemple #5
0
static void
zmqdrv_send(zmq_drv_t *drv, ErlIOVec *ev)
{
    ErlDrvBinary*  bin   = ev->binv[1];
    char*          bytes = bin->orig_bytes;
    uint32_t       idx   = ntohl(*(uint32_t*)(bytes+1));
    zmq_sock_info* si    = drv->get_socket_info(idx);
    uint32_t       flags = ntohl(*(uint32_t*)(bytes+5));
    void*          data  = (void *)(bytes + 9);
    size_t         size  = bin->orig_size - 9;

    if (idx > drv->zmq_socket_count || !si) {
        zmqdrv_error_code(drv, ENODEV);
        return;
    }

#ifdef ZMQDRV_DEBUG
    uint32_t events;
    size_t events_size = sizeof(events);
    zmq_getsockopt(si->socket, ZMQ_EVENTS, &events, &events_size);
    zmqdrv_fprintf("sending %p [idx=%d] %lu bytes (events=%d)\r\n", si->socket, idx, size, events);
#endif

    if (si->out_caller != 0) {
        // There's still an unwritten message pending
        zmqdrv_error_code(drv, EBUSY);
        return;
    }

    // Increment the reference count on binary so that zmq can
    // take ownership of it.
    driver_binary_inc_refc(bin);

    if (zmq_msg_init_data(&si->out_msg, data, size, &zmq_free_binary, bin)) {
        zmqdrv_error_code(drv, zmq_errno());
        driver_binary_dec_refc(bin);
        return;
    }

    if (zmq_send(si->socket, &si->out_msg, flags | ZMQ_NOBLOCK) == 0) {
        zmqdrv_ok(drv);
        zmqdrv_ready_input((ErlDrvData)drv, (ErlDrvEvent)si->fd);
    } else {
        int e = zmq_errno();
        if (e == EAGAIN) {
            // No msg returned to caller - make him wait until async
            // send succeeds
            si->out_caller = driver_caller(drv->port);
            return;
        }
        zmqdrv_error_code(drv, e);
    }
    zmq_msg_close(&si->out_msg);
}
Exemple #6
0
/* Put elements from vec at q tail */
int erts_ioq_enqv(ErtsIOQueue *q, ErtsIOVec *eiov, Uint skipbytes)
{
    int n;
    Uint len;
    Uint size = eiov->common.size - skipbytes;
    SysIOVec *iov;
    ErtsIOQBinary** binv;
    ErtsIOQBinary*  b;

    if (q == NULL)
	return -1;

    ASSERT(eiov->common.size >= skipbytes);
    if (eiov->common.size <= skipbytes)
	return 0;

    n = skip(eiov, skipbytes, &iov, &binv, &len);

    if (n < 0)
        return n;

    if (q->v_tail + n >= q->v_end)
	if (expandq(q, n, 1))
            return -1;

    /* Queue and reference all binaries (remove zero length items) */
    while(n--) {
	if ((len = iov->iov_len) > 0) {
	    if ((b = *binv) == NULL) { /* special case create binary ! */
		b = alloc_binary(len, iov->iov_base, (void**)&q->v_tail->iov_base,
                                 q->driver);
                if (!b) return -1;
		*q->b_tail++ = b;
		q->v_tail->iov_len = len;
		q->v_tail++;
	    }
	    else {
                if (q->driver)
                    driver_binary_inc_refc(&b->driver);
                else
                    erts_refc_inc(&b->nif.intern.refc, 1);
		*q->b_tail++ = b;
		*q->v_tail++ = *iov;
	    }
	}
	iov++;
	binv++;
    }
    q->size += size;      /* update total size in queue */
    return 0;
}
Exemple #7
0
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~
static void
wrap_zmq_send(zmq_drv_t *drv, const uint8_t* bytes, size_t size, ErlDrvBinary* bin)
{
    int     flags     = *bytes;
    void*   data      = (void *)(bytes+sizeof(uint8_t));
    size_t  data_size = size - sizeof(uint8_t);

    assert(sizeof(uint8_t) <= size);

    ErlDrvTermData caller = driver_caller(drv->port);

    if (drv->terminating)
    {
        reply_error(drv->port, caller, ETERM);
        return;
    }

    zmq_sock_info* si = drv->get_socket_info(caller);

    if (!si)
    {
        reply_error(drv->port, caller, ENODEV);
        return;
    }

    assert(0 == si->out_caller);

    zmqdrv_fprintf("send %p (flags: %d bytes: %u)\r\n", si->socket, flags, data_size);

    // Increment the reference count on binary so that zmq can take ownership of it.
    driver_binary_inc_refc(bin);

    if (zmq_msg_init_data(&si->out_msg, data, data_size, &zmqcb_free_binary, bin))
    {
        reply_error(drv->port, caller, zmq_errno());
        driver_binary_dec_refc(bin);
        return;
    }

    if (0 == zmq_send(si->socket, &si->out_msg, flags|ZMQ_NOBLOCK))
    {
        reply_ok(drv->port, caller);
        zmq_msg_close(&si->out_msg);
    }
    else if (ZMQ_NOBLOCK != (ZMQ_NOBLOCK & flags) && EAGAIN == zmq_errno())
    {
        // Caller requested blocking send
        // Can't send right now. Make the caller wait by not returning result
        zmqdrv_fprintf("send %p blocking\r\n", si->socket);

        si->out_flags = flags;
        si->out_caller = caller;

        if (!si->busy)
        {
            driver_select(drv->port, si->fd, ERL_DRV_READ, 1);
            si->busy = true;
        }
    }
    else
    {
        reply_error(drv->port, caller, zmq_errno());
        zmq_msg_close(&si->out_msg);
    }
}
Exemple #8
0
static void
enm_outputv(ErlDrvData drv_data, ErlIOVec *ev)
{
    EnmData* d = (EnmData*)drv_data;
    ErlIOVec qev;
    ErlDrvSizeT qtotal;
    struct nn_msghdr msghdr;
    int i, rc = -1, err;

    if (d->fd == -1 || d->protocol == NN_PULL || d->protocol == NN_SUB)
        return;
    qtotal = driver_peekqv(d->port, &qev);
    if (qtotal > 0) {
        memset(&msghdr, 0, sizeof msghdr);
        msghdr.msg_iov = (struct nn_iovec*)qev.iov;
        msghdr.msg_iovlen = qev.vsize;
        msghdr.msg_control = 0;
        err = 0;
        do {
            rc = enm_do_send(d, &msghdr, &err);
            if (rc < 0) {
                if (err == EAGAIN) {
                    d->b.writable = 0;
                    break;
                } else if (err != EINTR) {
                    char errstr[32];
                    switch (enm_errno_str(err, errstr)) {
                    case ENM_NANOMSG_ERROR:
                        driver_failure_atom(d->port, errstr);
                        break;
                    case ENM_POSIX_ERROR:
                        driver_failure_posix(d->port, err);
                        break;
                    case ENM_UNKNOWN_ERROR:
                        driver_failure(d->port, err);
                        break;
                    }
                    return;
                }
            }
        } while (err == EINTR);
    }
    /*
     * Do nothing if the message has no data
     */
    if (ev->size == 0 || ev->vsize == 0 ||
        (ev->vsize == 1 && *ev->binv == 0 && ev->iov->iov_len == 0))
        return;
    if (d->b.writable) {
        memset(&msghdr, 0, sizeof msghdr);
        msghdr.msg_iov = (struct nn_iovec*)ev->iov;
        msghdr.msg_iovlen = ev->vsize;
        msghdr.msg_control = 0;
        err = 0;
        do {
            rc = enm_do_send(d, &msghdr, &err);
            if (rc < 0) {
                if (err == EAGAIN) {
                    d->b.writable = 0;
                    break;
                } else if (err != EINTR) {
                    char errstr[32];
                    switch (enm_errno_str(err, errstr)) {
                    case ENM_NANOMSG_ERROR:
                        driver_failure_atom(d->port, errstr);
                        break;
                    case ENM_POSIX_ERROR:
                        driver_failure_posix(d->port, err);
                        break;
                    case ENM_UNKNOWN_ERROR:
                        driver_failure(d->port, err);
                        break;
                    }
                    return;
                }
            }
        } while (err == EINTR);
    }
    if (rc < 0 && !d->b.writable) {
        rc = 0;
        d->b.busy = 1;
        set_busy_port(d->port, d->b.busy);
        for (i = 0; i < ev->vsize; i++) {
            ErlDrvBinary* bin = 0;
            if (ev->binv[i] != 0) {
                bin = ev->binv[i];
                driver_binary_inc_refc(bin);
            } else if (ev->iov[i].iov_len > 0) {
                SysIOVec* vec = &ev->iov[i];
                bin = driver_alloc_binary(vec->iov_len);
                memcpy(bin->orig_bytes, vec->iov_base, vec->iov_len);
            }
            if (bin != 0)
                driver_enq_bin(d->port, bin, 0, bin->orig_size);
        }
        if (!d->b.write_poll)
            enm_write_select(d, 1);
    }
    if (rc > 0 && d->protocol == NN_SURVEYOR && d->b.active != ENM_FALSE)
        enm_read_select(d, 1);
}