コード例 #1
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_ok_binary(descriptor_t *desc, char *ptr, int beg_offset, int length)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_BINARY(msg, i, edtk_alloced_ptr2ErlDrvBinary(ptr),
                    beg_offset, length);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("%s: i = %d, ptr = 0x%lx, start = %d, end = %d",
    __FUNCTION__, i, ptr, beg_offset, length);
    res = driver_output_term(desc->port, msg, i);
    /* driver_output_term() incrs refc, and we're done, so decr refc */
    /*
    ** We _know_ that "ptr" points to memory allocated by
    ** edtk_driver_alloc_wrapper(), so edtk_alloced_ptr2ErlDrvBinary()
    ** is safe in this case.  If it weren't safe, then the binary
    ** must be returned by an xtra_return, which means we
    ** reply_ok_binary()) are never called!
    */
    driver_free_binary(edtk_alloced_ptr2ErlDrvBinary(ptr));
    edtk_debug("%s: res = %d", __FUNCTION__, res);
    return res;
}
コード例 #2
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void s1_ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data)
{
    descriptor_t        *desc = (descriptor_t *) drv_data;
    callstate_t *c = (callstate_t *) thread_data;
    int                 bytes, offset, i;
    char                *p = NULL;
    unsigned long       index = 0;

    edtk_debug("%s: cmd = %d", __FUNCTION__, c->cmd);
    if (c == NULL) {
        edtk_debug("%s: c == NULL", __FUNCTION__);
        return;
    }
    switch (c->cmd) {
    case S1_NULL:
        reply_ok(desc);
        break;
    case S1_OPEN:
        if (! c->o.__expect) {
            reply_error(desc, c->o.__expect_errval);
            break;
        }
        if (find_unused_fd_index(desc, &index) < 0) {
            reply_error(desc, ENOMEM);
        } else {
            desc->valmap_fd[index] = c->o.ret_int;
            reply_ok_valmap(desc, am_valmap_fd, index);
        }
        break;
    case S1_GETFD:
        reply_ok_num(desc, c->o.ret_int);
        break;
    case S1_SENDFD:
        if (c->o.__expect) {
            reply_ok_num(desc, c->o.ret_int_t);
        } else {
            reply_error(desc, c->o.__expect_errval);
        }
        break;
    case S1_RECEIVEFD:
        if (c->o.__expect) {
            reply_ok_num(desc, c->o.ret_int_t);
        } else {
            reply_error(desc, c->o.__expect_errval);
        }
        break;
    case S1_CLOSE:
        if (! c->o.__expect) {
            reply_error(desc, c->o.__expect_errval);
            break;
        }
        cleanup_valmap_fd_index(desc, c->i.__valmap_fd_index, 0);
        reply_ok_num(desc, c->o.ret_int);
        break;
    default:
        edtk_debug("%s: bogus command, should never happen", __FUNCTION__);
        break;
    }
    sys_free(c);
}
コード例 #3
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
invoke_s1_null(void *data)
{
    callstate_t *c = (callstate_t *) data;

    edtk_debug("%s: threadid = %lx", __FUNCTION__, pthread_self());
    null();
    edtk_debug("%s: threadid = %lx done", __FUNCTION__, pthread_self());
}
コード例 #4
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void cleanup_valmap_fd_index(descriptor_t *desc, int i, int do_cleanup_func)
{
    edtk_debug("%s: i = %d, do_cleanup_func = %d", __FUNCTION__, i, do_cleanup_func);
    if (do_cleanup_func) {
        edtk_debug("%s: calling func close", __FUNCTION__);
        close(desc->valmap_fd[i]);
    }
    desc->valmap_fd[i] = -1;
}
コード例 #5
0
ファイル: erl_driver_tk.c プロジェクト: XinliNiu/jungerl
void
edtk_driver_free_wrapper(void *p)
{
    ErlDrvBinary	*eb;

    edtk_debug("%s: top", __FUNCTION__);
    if ((eb = edtk_alloced_ptr2ErlDrvBinary(p)) != NULL) {
	edtk_debug("%s: eb = 0x%lx p = 0x%lx", __FUNCTION__, eb, p);
	driver_free_binary(eb);
    }
}
コード例 #6
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
invoke_s1_getfd(void *data)
{
    callstate_t *c = (callstate_t *) data;

    c = c;
    edtk_debug("%s: threadid = %lx", __FUNCTION__, pthread_self());
    c->o.ret_int = my_getfd(
                          c->i.fd
                        );
    edtk_debug("%s: threadid = %lx done", __FUNCTION__, pthread_self());
}
コード例 #7
0
ファイル: erl_driver_tk.c プロジェクト: XinliNiu/jungerl
void *
edtk_driver_alloc_wrapper(size_t size)
{
    ErlDrvBinary	*eb;

    edtk_debug("%s: top", __FUNCTION__);
    if ((eb = driver_alloc_binary(size)) != NULL) {
	edtk_debug("%s: size %lu eb = 0x%lx orig_bytes = 0x%lx", __FUNCTION__, size, eb, eb->orig_bytes);
	return eb->orig_bytes;
    } else {
	return NULL;
    }
}
コード例 #8
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_ok(descriptor_t *desc)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_TUPLE(msg, i, 2);
    edtk_debug("reply_ok: i = %d", i);
    res = driver_output_term(desc->port, msg, i);
    edtk_debug("reply_ok: res = %d", res);
    return res;
}
コード例 #9
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_error_atom(descriptor_t *desc, ErlDrvTermData atom)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_error);
    i = LOAD_ATOM(msg, i, atom);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("%s: i = %d", __FUNCTION__, i);
    res = driver_output_term(desc->port, msg, i);
    edtk_debug("%s: res = %d", __FUNCTION__, res);
    return res;
}
コード例 #10
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_ok_num(descriptor_t *desc, unsigned long num)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_INT(msg, i, num);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("%s: i = %d, num = %lu", __FUNCTION__, i, num);
    res = driver_output_term(desc->port, msg, i);
    edtk_debug("%s: res = %d", __FUNCTION__, res);
    return res;
}
コード例 #11
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
s1_stop(ErlDrvData drv_data)
{
    descriptor_t        *desc = (descriptor_t *) drv_data;
    int                 i = 0;
    ErlDrvPort          port;
    int                 still_in_use = 0;

    i = i;
    if (desc == NULL) {
        edtk_debug("%s: drv_data == NULL", __FUNCTION__);
        return;
    }
    edtk_debug("%s: port = %ld", __FUNCTION__, desc->port);

    for (i = 0; i < 32; i++) {
        if (desc->valmap_fd[i] != -1) {
            cleanup_valmap_fd_index(desc, i, 1);
        }
    }

    if (! still_in_use) {
        port = desc->port;
        sys_free(desc);
        edtk_debug("%s: port = %ld finished", __FUNCTION__, port);
    } else {
        /*
        ** XXX Oi, this is a sticky problem.  This port is being shut
        ** down, but we've still got some valmaps in use.  We have no
        ** way to tell the VM that we cannot be shut down safely right
        ** now, so what in the heck do we do?  It seems to me that we
        ** have two choices:
        **   1. Block the entire VM until all valmaps are idle, then
        **      clean them up and then return.
        **   2. Create a new thread that will take care of monitoring
        **      the valmaps & doing their final cleanup.  This stop
        **      function, executing in the main thread, can return
        **      to the VM right away.
        ** For the sake of simplicity, I'm going to implement #1
        ** for now.  This will get more complicated once EDTK supports
        ** private worker threads, so we won't bother getting fancy
        ** for now.
        */
        edtk_debug("%s: port = %ld has %d valmaps still in use!", __FUNCTION__, desc->port, still_in_use);
        sleep(1);
        s1_stop(drv_data);              /* Hope we don't run out of stack */
    }
}
コード例 #12
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static ErlDrvData
s1_start(ErlDrvPort port, char *args)
{
    descriptor_t        *desc;
    int                 i = 0;

    i = i;
    edtk_debug("%s: starting, port = %ld, args = 0x%lx, %s", __FUNCTION__,
               port, (unsigned long) args, args);

    if ((desc = (descriptor_t *) sys_alloc(sizeof(descriptor_t))) == NULL) {
        return ERL_DRV_ERROR_GENERAL;
    }
    memset(desc, 0, sizeof(descriptor_t));
    desc->port = port;
    desc->nextxid = 1;
    for (i = 0; i < 32; i++) {
        desc->valmap_fd[i] = -1;
    }
    /* TODO: Finish initializing descriptor members */

    /* TODO: Take care of other port initialization tasks */

    return (ErlDrvData) desc;
}
コード例 #13
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_error(descriptor_t *desc, int errnum)
{
    ErlDrvTermData      msg[24];
    int                 i = 0;
    int                 res;

    edtk_debug("reply_error: errnum = %d", errnum);
    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_error);
    i = LOAD_INT(msg, i, errnum);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("reply_error: i = %d", i);
    res = driver_output_term(desc->port, msg, i);
    edtk_debug("reply_error: res = %d", res);
    return res;
}
コード例 #14
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void cleanup_valmap_fd_all(descriptor_t *desc, int do_cleanup_func)
{
    int i;

    edtk_debug("%s: do_cleanup_func = %d", __FUNCTION__, do_cleanup_func);
    for (i = 0; i < 32; i++) {
        cleanup_valmap_fd_index(desc, i, do_cleanup_func);
    }
}
コード例 #15
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
invoke_s1_open(void *data)
{
    callstate_t *c = (callstate_t *) data;

    edtk_debug("%s: threadid = %lx", __FUNCTION__, pthread_self());
    c->o.ret_int = my_open(c->i.filename,
                           c->i.flags);
    if (c->o.ret_int >= 0) {
        c->o.__expect = 1;
    } else {
        c->o.__expect = 0;
        c->o.__expect_errval = errno;
        /* Danger!  Do not put debugging statement before saving error val! */
        edtk_debug("%s: threadid = %lx expectation failed!", __FUNCTION__, pthread_self());
    }
    edtk_debug("%s: threadid = %lx done", __FUNCTION__, pthread_self());
}
コード例 #16
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int reply_ok_valmap(descriptor_t *desc, ErlDrvTermData valmap_atom,
                unsigned long valmap_index)
{
    ErlDrvTermData      msg[15];
    int                 i = 0;
    int                 res;

    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_ATOM(msg, i, valmap_atom);
    i = LOAD_INT(msg, i, valmap_index);
    i = LOAD_TUPLE(msg, i, 2);
    i = LOAD_TUPLE(msg, i, 3);
    edtk_debug("reply_ok_valmap: i = %d", i);
    res = driver_output_term(desc->port, msg, i);
    edtk_debug("reply_ok_valmap: res = %d", res);
    return res;
}
コード例 #17
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
invoke_s1_receivefd(void *data)
{
    callstate_t *c = (callstate_t *) data;

    c = c;
    edtk_debug("%s: threadid = %lx", __FUNCTION__, pthread_self());
    c->o.ret_int_t = my_receivefd(
                          c->i.unixdom_fd
                        );
    if (c->o.ret_int_t >= 0) {
        c->o.__expect = 1;
    } else {
        c->o.__expect = 0;
        c->o.__expect_errval = errno;
        /* Danger!  Do not put debugging statement before saving error val! */
        edtk_debug("%s: threadid = %lx expectation failed!", __FUNCTION__, pthread_self());
    }
    edtk_debug("%s: threadid = %lx done", __FUNCTION__, pthread_self());
}
コード例 #18
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void
s1_output(ErlDrvData drv_data, char *buf, int len)
{
    /*
    ** Nobody should be calling this function because we've
    ** defined the "outputv" driver method, which BEAM will always
    ** used if it's available.  I just put a debug statement in
    ** here so that I might actually notice if the impossible ever
    ** happens....
    */
    edtk_debug("%s: XXX someone tried to call us, silly", __FUNCTION__);
}
コード例 #19
0
ファイル: erl_driver_tk.c プロジェクト: XinliNiu/jungerl
ErlDrvBinary *
edtk_alloced_ptr2ErlDrvBinary(void *p)
{
    ErlDrvBinary	stackeb;
    int			offset = stackeb.orig_bytes - (char *) &stackeb;

    if (p != NULL) {
	edtk_debug("%s: p = 0x%lx eb = 0x%lx", __FUNCTION__, p, (ErlDrvBinary *) ((char *) p - offset));
	return (ErlDrvBinary *) ((char *) p - offset);
    } else {
	return NULL;
    }
}
コード例 #20
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static int
s1_control(ErlDrvData drv_data, unsigned int command,
                  char *buf, int len, char **rbuf, int rlen)
{
    char        *ret = *rbuf;
    int         retlen;

    /*
    ** Nobody should be calling this function either.
    */
    ret[0] = 1;
    retlen = 1;
    edtk_debug("%s: XXX someone tried to call us, silly", __FUNCTION__);
    return retlen;
}
コード例 #21
0
ファイル: erl_driver_tk.c プロジェクト: XinliNiu/jungerl
void *
edtk_driver_realloc_wrapper(void *p, size_t size)
{
    ErlDrvBinary	*eb, *neweb;

    edtk_debug("%s: top", __FUNCTION__);
    if ((eb = edtk_alloced_ptr2ErlDrvBinary(p)) != NULL) {
	if ((neweb = driver_realloc_binary(eb, size)) != NULL) {
	    return neweb->orig_bytes;
	} else {
	    return NULL;
	}
    } else {
	return NULL;
    }
}
コード例 #22
0
ファイル: unixdom_drv.c プロジェクト: paulgray/unixdom_drv
static void s1_outputv(ErlDrvData drv_data, ErlIOVec *ev)
{
    descriptor_t        *desc = (descriptor_t *) drv_data;
    unsigned char       cmd;
    int                 p = 0, q = 1;
    callstate_t         *c = NULL;
    int                 do_async_call = default_async_calls;
    unsigned long       binlen;
    int                 index;
    void                *tmp = NULL;

    binlen = binlen;
    index = index;
    tmp = tmp;
    if (desc == NULL || ev == NULL || ev->size < 1) {
        edtk_debug("%s: bad arg(s)", __FUNCTION__);
        return;
    }
    if (! EV_GET_CHAR(ev, &cmd, &p, &q)) {
        edtk_debug("%s: empty command", __FUNCTION__);
        reply_error(desc, EINVAL);
    }
    if ((c = sys_alloc(sizeof(callstate_t))) == NULL) {
        reply_error(desc, ENOMEM);
        return;
    }
    c->cmd = cmd;
    c->key = NULL;
    c->free = sys_free;
    c->xid = 0;         /* XXX unused right now */
    c->o.__expect = 1;  /* Default is that expectation is always met */

    edtk_debug("%s: my threadid = %lx, cmd = %d", __FUNCTION__, pthread_self(), cmd);
    switch (cmd) {
    case S1_DEBUG:
        EV_GET_UINT32(ev, &edtk_debug_flag, &p, &q);
        reply_ok_num(desc, edtk_debug_flag);    /* Immediate reply */
        sys_free(c);
        c = NULL;
        break;
    case S1_NULL:
        c->invoke = invoke_s1_null;
        break;
    case S1_OPEN:
        c->invoke = invoke_s1_open;
        EV_GET_UINT32(ev, &binlen, &p, &q);
        c->i.filename = (char *) EV_GETPOS(ev, p, q);
        if (edtk_ev_forward_N(ev, binlen, &p, &q, 1) < 0) {
            goto error;
        }
        EV_GET_UINT32(ev, &c->i.flags, &p, &q);
        break;
    case S1_GETFD:
        c->invoke = invoke_s1_getfd;
        EV_GET_UINT32(ev, &index, &p, &q);
        if (desc->valmap_fd[index] == -1) {
            goto error;
        } else {
            edtk_debug("%s: valmap fd index %d = 0x%lx", __FUNCTION__, index, desc->valmap_fd[index]);
            c->i.fd = desc->valmap_fd[index];
            c->i.__valmap_fd_index = index;
        }
        break;
    case S1_SENDFD:
        c->invoke = invoke_s1_sendfd;
        EV_GET_UINT32(ev, &c->i.unixdom_fd, &p, &q);
        EV_GET_UINT32(ev, &c->i.fd_to_be_sent, &p, &q);
        break;
    case S1_RECEIVEFD:
        c->invoke = invoke_s1_receivefd;
        EV_GET_UINT32(ev, &c->i.unixdom_fd, &p, &q);
        break;
    case S1_CLOSE:
        c->invoke = invoke_s1_close;
        EV_GET_UINT32(ev, &index, &p, &q);
        if (index == -1 && 0 == 1) {
            edtk_debug("%s: valmap fd index %d = default value 0x%lx", __FUNCTION__, index, -1);
            c->i.fd = -1;
            c->i.__valmap_fd_index = -1;
        } else if (desc->valmap_fd[index] == -1) {
            goto error;
        } else {
            edtk_debug("%s: valmap fd index %d = 0x%lx", __FUNCTION__, index, desc->valmap_fd[index]);
            c->i.fd = desc->valmap_fd[index];
            c->i.__valmap_fd_index = index;
        }
        break;
    }

    if (c != NULL) {
        if (do_async_call) {
            driver_async(desc->port, c->key, c->invoke, c, c->free);
        } else {
            /*
            ** Execute the bottom half right away, then send the result.
            */
            (*(c->invoke))((void *) c);
            s1_ready_async((ErlDrvData) desc, (ErlDrvThreadData) c);
            /*
            ** c is already freed for us by s1_ready_async()
            */
        }
    }
    return;

  error:
    if (c != NULL) {
        sys_free(c);
    }
    reply_error_atom(desc, am_badarg);
}