Esempio n. 1
0
dthread_t* dthread_start(ErlDrvPort port,
			 void* (*func)(void* arg),
			 void* arg, int stack_size)
{
    ErlDrvThreadOpts* opts = NULL;
    dthread_t* thr = NULL;

    if (!(thr = DALLOC(sizeof(dthread_t))))
	return 0;

    if (dthread_init(thr, port) < 0)
	goto error;

    if (!(opts = erl_drv_thread_opts_create("dthread_opts")))
	goto error;

    opts->suggested_stack_size = stack_size;
    thr->arg = arg;

    if (erl_drv_thread_create("dthread", &thr->tid, func, thr, opts) < 0)
	goto error;
    erl_drv_thread_opts_destroy(opts);
    return thr;

error:
    dthread_finish(thr);
    if (opts)
        erl_drv_thread_opts_destroy(opts);
    dthread_finish(thr);
    DFREE(thr);
    return 0;
}
Esempio n. 2
0
// Initialize thread structure
int dthread_init(dthread_t* thr, ErlDrvPort port)
{
    ErlDrvSysInfo sys_info;

    memset(thr, 0, sizeof(dthread_t));
    dthread_signal_init(thr);
    driver_system_info(&sys_info, sizeof(ErlDrvSysInfo));
    // smp_support is used for message passing from thread to
    // calling process. if SMP is supported the message will go
    // directly to sender, otherwise it must be sent to port 
    thr->smp_support = sys_info.smp_support;
    thr->port = port;
    thr->dport = driver_mk_port(port);
    thr->owner = driver_connected(port);

    if (!(thr->iq_mtx = erl_drv_mutex_create("iq_mtx")))
	return -1;
#ifdef __WIN32__
    // create a manual reset event
    if (!(thr->iq_signal[0] = (ErlDrvEvent)
	  CreateEvent(NULL, TRUE, FALSE, NULL))) {
	dthread_finish(thr);
	return -1;
    }
    DEBUGF("dthread_init: handle=%d", DTHREAD_EVENT(thr->iq_signal[0]));
#else
    {
	int pfd[2];
	if (pipe(pfd) < 0) {
	    dthread_finish(thr);
	    return -1;
	}
	DEBUGF("dthread_init: pipe[0]=%d,pidp[1]=%d", pfd[0], pfd[1]);
	thr->iq_signal[0] = (ErlDrvEvent) ((long)pfd[0]);
	thr->iq_signal[1] = (ErlDrvEvent) ((long)pfd[1]);
	INFOF("pipe: %d,%d", pfd[0], pfd[1]);
    }
#endif
    return 0;
}
Esempio n. 3
0
static ErlDrvData uart_drv_start(ErlDrvPort port, char* command)
{
    (void) command;
    drv_ctx_t* ctx = NULL;

    INFOF("memory allocated: %ld", dlib_allocated());
    INFOF("total memory allocated: %ld", dlib_total_allocated());

    ctx = DZALLOC(sizeof(drv_ctx_t));

    dthread_init(&ctx->self, port);

    if (strncmp(command, "uart_drv", 8) == 0)
	command += 8;
    if (*command == ' ')
	command++;
    DEBUGF("uart_drv: start (%s)", command);


    if (strcmp(command, "ftdi") == 0) {
#ifdef HAVE_FTDI
	ctx->other = dthread_start(port, uart_ftdi_main, &ctx->self, 4096);
	DEBUGF("uart_drv: ftdi thread = %p", ctx->other);
#endif
    }
    else {
#ifdef __WIN32__
	if ((*command == '\0') || (strcmp(command, "win32") == 0)) {
	    ctx->other = dthread_start(port, uart_win32_main, &ctx->self, 4096);
	    DEBUGF("uart_drv: win32 thread = %p", ctx->other);
	}
#else 
	if ((*command == '\0') || (strcmp(command, "unix") == 0)) {
	    ctx->other = dthread_start(port, uart_unix_main, &ctx->self, 4096);
	    DEBUGF("uart_drv: unix thread = %p", ctx->other);
	}
#endif
    }
    if (ctx->other == NULL) {
	dthread_finish(&ctx->self);
	DFREE(ctx);
	return ERL_DRV_ERROR_BADARG;
    }

    dthread_signal_use(&ctx->self, 1);
    dthread_signal_select(&ctx->self, 1);

    set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
    return (ErlDrvData) ctx;
}
Esempio n. 4
0
static void uart_drv_stop(ErlDrvData d)
{
    drv_ctx_t* ctx = (drv_ctx_t*) d;
    void* value;    

    DEBUGF("uart_drv_stop: called");
    dthread_stop(ctx->other, &ctx->self, &value);

    DEBUGF("uart_drv_stop: signal_use=0");
    dthread_signal_use(&ctx->self, 0);

    DEBUGF("uart_drv_stop: dthread_finish");
    dthread_finish(&ctx->self);
    DFREE(ctx);
    INFOF("memory allocated: %ld", dlib_allocated());
    INFOF("total memory allocated: %ld", dlib_total_allocated());
}
Esempio n. 5
0
int dthread_stop(dthread_t* target, dthread_t* source, 
		 void** exit_value)
{
    dmessage_t* mp;
    int r;

    if (!(mp = dmessage_create(DTHREAD_STOP, NULL, 0)))
	return -1;
    dthread_send(target, source, mp);

    DEBUGF("dthread_stop: wait to join");
    r = erl_drv_thread_join(target->tid, exit_value);
    DEBUGF("dthread_stop: thread_join: return=%d, exit_value=%p", r, *exit_value);

    dthread_signal_finish(target, 1);
    dthread_finish(target);
    DFREE(target);
    return 0;
}