static ErlDrvData start(ErlDrvPort port, char *command) { Otp9302Data *data; ErlDrvSysInfo sys_info; data = driver_alloc(sizeof(Otp9302Data)); if (!data) return ERL_DRV_ERROR_GENERAL; data->port = port; driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); data->smp = sys_info.smp_support; if (!data->smp) { data->msgq.start = NULL; data->msgq.end = NULL; data->msgq.mtx = erl_drv_mutex_create(""); if (!data->msgq.mtx) { driver_free(data); return ERL_DRV_ERROR_GENERAL; } } return (ErlDrvData) data; }
static ErlDrvData tcbdb_start (ErlDrvPort port, char* buf) { ErlDrvSysInfo info; TcDriverData* d = (TcDriverData*) driver_alloc (sizeof (TcDriverData)); (void) buf; memset (d, 0, sizeof (TcDriverData)); d->ref_count = 1; d->port = port; d->bdb = tcbdbnew (); driver_system_info (&info, sizeof (info)); if (info.thread_support && info.async_threads > 0) { d->async_threads = 1; } d->cur = tcbdbcurnew (d->bdb); init_handlers (d->handlers); d->magic = ((intptr_t) d) >> 8; return (ErlDrvData) d; }
static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { char *res_str; PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command)); switch (command) { case ERTS_FP_THREAD_TEST: { ErlDrvTid tid; ErlDrvSysInfo info; driver_system_info(&info, sizeof(ErlDrvSysInfo)); if (!info.thread_support) res_str = "skip: no thread support"; else if (0 != erl_drv_thread_create("test", &tid, do_test, NULL, NULL)) res_str = "failed to create thread"; else if (0 != erl_drv_thread_join(tid, &res_str)) res_str = "failed to join thread"; break; } case ERTS_FP_CONTROL_TEST: res_str = do_test(NULL); break; default: res_str = "unknown command"; break; } done: { int res_len = strlen(res_str); if (res_len > rlen) { char *abuf = driver_alloc(sizeof(char)*res_len); if (!abuf) return 0; *rbuf = abuf; } memcpy((void *) *rbuf, (void *) res_str, res_len); return res_len; } }
// 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; }
// Called by the emulator when the driver is starting. static ErlDrvData start_driver(ErlDrvPort port, char *buff) { EdbcOciPortData *pd = zalloc(port, sizeof(EdbcOciPortData)); if (pd == NULL) { // TODO: use ERL_DRV_ERROR_ERRNO and provide out-of-memory info return ERL_DRV_ERROR_GENERAL; } ErlDrvSysInfo sys_info; driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); pd->send_term_requires_lock = (sys_info->smp_support == 0); pd->port = (void*)port; pd->owner = driver_connected(port); pd->mutex = erl_drv_mutex_create("edbc_oci_port_instance_mutex"); // some fields can't be initialized until we've got our hands on // the relevant configuration data at runtime... pd->worker_pool = NULL; pd->log = NULL; return (ErlDrvData)pd; };
static int innostore_drv_init() { char log_filename[_POSIX_PATH_MAX]; size_t log_filename_size = sizeof(log_filename); ErlDrvSysInfo sys_info; G_ENGINE_STATE_LOCK = erl_drv_mutex_create("innostore_state_lock"); G_LOGGER_LOCK = erl_drv_mutex_create("innostore_logger_lock"); // Check if this is beam.smp - cannot run under beam // due to restrictions with driver_send_term driver_system_info(&sys_info, sizeof(sys_info)); if (sys_info.smp_support == 0) { log("Innostore only supports the SMP runtime, add -smp enable"); return -1; } // Initialize Inno's memory subsystem if (ib_init() != DB_SUCCESS) { return -1; } // Set up the logger if (erl_drv_getenv("INNOSTORE_LOG", log_filename, &log_filename_size) == 0) { set_log_file(log_filename); } else { set_log_file(NULL); } return 0; }
void enif_system_info(ErlNifSysInfo *sip, size_t si_size) { driver_system_info(sip, si_size); }
static int control(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen) { int res; char *str; size_t slen, slen2; ErlDrvPort port = (ErlDrvPort) drv_data; unsigned deadbeef[] = {0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef}; ErlDrvSysInfo *sip = driver_alloc(ERL_DRV_SYS_INFO_SIZE + sizeof(deadbeef)); char *beyond_end_format = "error: driver_system_info() wrote beyond end " "of the ErlDrvSysInfo struct"; char *buf_overflow_format = "error: Internal buffer overflow"; if (!sip) { driver_failure_atom(port, "enomem"); return 0; } memset((char *) sip, 0xed, ERL_DRV_SYS_INFO_SIZE); memcpy(((char *) sip) + ERL_DRV_SYS_INFO_SIZE, (char *) &deadbeef[0], sizeof(deadbeef)); driver_system_info(sip, ERL_DRV_SYS_INFO_SIZE); slen = sys_info_drv_max_res_len(sip); slen2 = strlen(beyond_end_format) + 1; if (slen2 > slen) slen = slen2; slen2 = strlen(buf_overflow_format) + 1; if (slen2 > slen) slen = slen2; str = driver_alloc(slen); if (!str) { driver_free(sip); driver_failure_atom(port, "enomem"); return 0; } *rbuf = str; /* Check that the emulator didn't write beyond ERL_DRV_SYS_INFO_SIZE */ if (memcmp(((char *) sip) + ERL_DRV_SYS_INFO_SIZE, (char *) &deadbeef[0], sizeof(deadbeef)) != 0) { res = sprintf(str, beyond_end_format); } else { res = sys_info_drv_sprintf_sys_info(sip, str); if (res > slen) res = sprintf(str, buf_overflow_format); } driver_free(sip); return res; }