Exemple #1
0
static void do_start(void* arg)
{
    PortState* state = (PortState*)arg;

    erl_drv_mutex_lock(G_ENGINE_STATE_LOCK);
    if (G_ENGINE_STATE == ENGINE_STOPPED)
    {
        // Engine was stopped; set the flag, unlock and run the start
        G_ENGINE_STATE = ENGINE_STARTING;
        erl_drv_mutex_unlock(G_ENGINE_STATE_LOCK);

        // Run the startup without holding any lock -- this can take a while
        // if we are recovering from previous errors
        ib_err_t error = ib_startup("barracuda");

        if (error == DB_SUCCESS)
        {
            // Make sure the innokeystore database exists
            // TODO: Avoid hard-coding the db name here...
            if (ib_database_create("innokeystore") != IB_TRUE)
            {
                error = DB_ERROR;
            }
        }

        // Relock and sort out results
        erl_drv_mutex_lock(G_ENGINE_STATE_LOCK);
        if (error == DB_SUCCESS)
        {
            G_ENGINE_STATE = ENGINE_STARTED;
            send_ok(state);
        }
        else
        {
            G_ENGINE_STATE = ENGINE_STOPPED;
            send_error_str(state, ib_strerror(error));
        }
    }
    else if (G_ENGINE_STATE == ENGINE_STARTED)
    {
        // another thread has already completed startup
        send_ok(state);
    }
    else
    {
        // Engine was not in stopped state when do_start was called.
        // Probably due to multiple threads trying to start at the
        // same time.
        assert(G_ENGINE_STATE == ENGINE_STARTING);
        send_error_atom(state, "starting");        
    }

    erl_drv_mutex_unlock(G_ENGINE_STATE_LOCK);
}
Exemple #2
0
static void innostore_drv_stop(ErlDrvData handle)
{
    PortState* state = (PortState*)handle;

    // Grab the worker lock, in case we have an job running
    erl_drv_mutex_lock(state->worker_lock);

    // Signal the shutdown and wait until the current operation has completed
    state->shutdown_flag = 1;
    erl_drv_cond_signal(state->worker_cv);

    while (state->op)
    {
        erl_drv_cond_wait(state->worker_cv, state->worker_lock);
    }

    // If the port state is not marked as READY, close the cursor and abort the txn
    if (state->port_state != STATE_READY)
    {
        ib_cursor_close(state->cursor);
        ib_trx_rollback(state->txn);
    }

    // No pending jobs and we have the lock again -- join our worker thread
    erl_drv_cond_signal(state->worker_cv);
    erl_drv_mutex_unlock(state->worker_lock);
    erl_drv_thread_join(state->worker, 0);

    // Cleanup
    erl_drv_cond_destroy(state->worker_cv);
    erl_drv_mutex_destroy(state->worker_lock);
    driver_free(handle);
}
Exemple #3
0
int start_native_gui(wxe_data *sd)
{
  int res;
  wxe_status_m = erl_drv_mutex_create((char *) "wxe_status_m");
  wxe_status_c = erl_drv_cond_create((char *)"wxe_status_c");

  wxe_batch_locker_m = erl_drv_mutex_create((char *)"wxe_batch_locker_m");
  wxe_batch_locker_c = erl_drv_cond_create((char *)"wxe_batch_locker_c");
  init_caller = driver_connected(sd->port_handle);

#ifdef __DARWIN__
  res = erl_drv_steal_main_thread((char *)"wxwidgets",
				  &wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL);
#else
  ErlDrvThreadOpts *opts = erl_drv_thread_opts_create((char *)"wx thread");
  opts->suggested_stack_size = 8192;
  res = erl_drv_thread_create((char *)"wxwidgets",
			      &wxe_thread,wxe_main_loop,(void *) sd->pdl,opts);
  erl_drv_thread_opts_destroy(opts);
#endif
  if(res == 0) {
    erl_drv_mutex_lock(wxe_status_m);
    for(;wxe_status == WXE_NOT_INITIATED;) {
      erl_drv_cond_wait(wxe_status_c, wxe_status_m);
    }
    erl_drv_mutex_unlock(wxe_status_m);
    return wxe_status;
  } else {
    wxString msg;
    msg.Printf(wxT("Erlang failed to create wxe-thread %d\r\n"), res);
    send_msg("error", &msg);
    return -1;
  }
}
Exemple #4
0
void WxeApp::dispatch_cmds() {
  erl_drv_mutex_lock(wxe_batch_locker_m);
  int level = dispatch(wxe_batch_cb_saved, 0, WXE_STORED);
  dispatch(wxe_batch, level, WXE_NORMAL);
  wxe_batch_caller = 0;
  erl_drv_mutex_unlock(wxe_batch_locker_m);
}
Exemple #5
0
// Should have  erl_drv_mutex_lock(wxe_batch_locker_m); 
// when entering this function and it should be released 
// afterwards
int WxeApp::dispatch(wxList * batch, int blevel, int list_type) 
{
  int ping = 0;
  // erl_drv_mutex_lock(wxe_batch_locker_m);  must be locked already
  while(true) 
    {
      if (batch->size() > 0) {
	for( wxList::compatibility_iterator node = batch->GetFirst();
	     node;
	     node = batch->GetFirst())
	  {
	    wxeCommand *event = (wxeCommand *)node->GetData();
	    batch->Erase(node);
	    switch(event->op) {
	    case WXE_BATCH_END:
	      {--blevel; }
	      break;
	    case WXE_BATCH_BEGIN:
	      {blevel++; }
	      break;
	    case WXE_DEBUG_PING:
	      // When in debugger we don't want to hang waiting for a BATCH_END 
	      // that never comes, because a breakpoint have hit.
	      ping++;
	      if(ping > 2) 
		blevel = 0;
	      break;
	    case WXE_CB_RETURN:
	      // erl_drv_mutex_unlock(wxe_batch_locker_m); should be called after
	      // whatever cleaning is necessary
	      memcpy(cb_buff, event->buffer, event->len);
	      return blevel;
	    default:
	      erl_drv_mutex_unlock(wxe_batch_locker_m);	      
	      if(event->op < OPENGL_START) {
		// fprintf(stderr, "  c %d (%d) \r\n", event->op, blevel);
		wxe_dispatch(*event);
	      } else {
		gl_dispatch(event->op,event->buffer,event->caller,event->bin);
	      }
	      erl_drv_mutex_lock(wxe_batch_locker_m);
	      break;
	    }
	    delete event;
	  }
      } else {
	if((list_type == WXE_STORED) || (blevel <= 0 && list_type == WXE_NORMAL)) {
	  // erl_drv_mutex_unlock(wxe_batch_locker_m); should be called after
	  // whatever cleaning is necessary
	  return blevel;
	}
	// sleep until something happens
	//fprintf(stderr, "%s:%d sleep %d %d %d %d \r\n", __FILE__, __LINE__, batch->size(), callback_returned, blevel, is_callback);fflush(stderr);
	wxe_batch_caller++;
	while(batch->size() == 0) {
	  erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m);
	}
      }
    }
}
Exemple #6
0
// Init wx-widgets thread 
bool WxeApp::OnInit()
{
  /* Create a dummy window so wxWidgets don't automagicly quits the main loop 
     after the last window */
  global_me = new wxeMemEnv();
  wxe_batch = new wxList;
  wxe_batch_cb_saved = new wxList;

  create_dummy_window();
  wxe_ps_init();

  wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED);

  this->Connect(wxID_ANY, wxEVT_IDLE, 
		(wxObjectEventFunction) (wxEventFunction) &WxeApp::idle);
  this->Connect(CREATE_PORT, wxeEVT_META_COMMAND, 
		(wxObjectEventFunction) (wxEventFunction) &WxeApp::newMemEnv);
  this->Connect(DELETE_PORT, wxeEVT_META_COMMAND, 
		(wxObjectEventFunction) (wxEventFunction) &WxeApp::destroyMemEnv);
  this->Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND, 
		(wxObjectEventFunction) (wxEventFunction) &WxeApp::shutdown);

//   fprintf(stderr, "Size void* %d: long %d long long %d int64 %d \r\n",
// 	  sizeof(void *), sizeof(long), sizeof(long long), sizeof(wxInt64));
  initEventTable();
  wxInitAllImageHandlers();
  init_nonconsts(global_me, init_caller);
  erl_drv_mutex_lock(wxe_status_m);
  wxe_status = WXE_INITIATED;
  gl_initiated = FALSE;   
  erl_drv_cond_signal(wxe_status_c);
  erl_drv_mutex_unlock(wxe_status_m);
  return TRUE;
}
Exemple #7
0
void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process) {
  int callback_returned = 0;
  while(true) {
    if (batch->size() > 0) {
      for( wxList::compatibility_iterator node = batch->GetFirst();
	   node;
	   node = batch->GetFirst())
	{
	  wxeCommand *event = (wxeCommand *)node->GetData();
	  wxeMemEnv *memenv = getMemEnv(event->port);
	  batch->Erase(node);
	  if(event->caller == process ||  // Callbacks from CB process only 
	     event->op == WXE_CB_START || // Recursive event callback allow
	     // Allow connect_cb during CB i.e. msg from wxe_server.
	     (memenv && event->caller == memenv->owner)) 
	    {
	      switch(event->op) {
	      case WXE_BATCH_END:
	      case WXE_BATCH_BEGIN:
	      case WXE_DEBUG_PING:
		break;
	      case WXE_CB_RETURN:
		memcpy(cb_buff, event->buffer, event->len);
		callback_returned = 1;
		return;
	      case WXE_CB_START:
		// CB start from now accept message from CB process only
		process = event->caller;
		break;
	      default:
		erl_drv_mutex_unlock(wxe_batch_locker_m);
		if(event->op < OPENGL_START) {
		  // fprintf(stderr, "  cb %d \r\n", event->op);
		  wxe_dispatch(*event);
		} else {
		  gl_dispatch(event->op,event->buffer,event->caller,event->bin);
		}
		erl_drv_mutex_lock(wxe_batch_locker_m);
		break;
		if(callback_returned) 
		  return;
	      }
	      delete event;
	    } else {
	    // fprintf(stderr, "  sav %d \r\n", event->op);
	    temp->Append(event);
	  }
	}
    } else {
      if(callback_returned) {
	return;
      }
      // sleep until something happens
      //fprintf(stderr, "%s:%d sleep %d %d %d %d \r\n", __FILE__, __LINE__, batch->size(), callback_returned, blevel, is_callback);fflush(stderr);
      while(batch->size() == 0) {
	erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m);
      }
    }
  }
}
Exemple #8
0
int start_native_gui(wxe_data *sd)
{
  int res;
  wxe_status_m = erl_drv_mutex_create((char *) "wxe_status_m");
  wxe_status_c = erl_drv_cond_create((char *)"wxe_status_c");

  wxe_batch_locker_m = erl_drv_mutex_create((char *)"wxe_batch_locker_m");
  wxe_batch_locker_c = erl_drv_cond_create((char *)"wxe_batch_locker_c");
  init_caller = driver_connected(sd->port); 

  if((res = erl_drv_thread_create((char *)"wxwidgets",
				  &wxe_thread,wxe_main_loop,(void *) sd->pdl,NULL)) == 0) {
    erl_drv_mutex_lock(wxe_status_m);
    for(;wxe_status == WXE_NOT_INITIATED;) {
      erl_drv_cond_wait(wxe_status_c, wxe_status_m);
    }
    erl_drv_mutex_unlock(wxe_status_m);
    return wxe_status;
  } else {
    wxString msg;
    msg.Printf(wxT("Erlang failed to create wxe-thread %d\r\n"), res);
    send_msg("error", &msg);
    return -1;
  }
}
Exemple #9
0
void mutex_unlock(mutex_t* mutex){
#ifdef USE_PTHREAD
  pthread_mutex_unlock(mutex);
#elif defined  USE_ETHREAD
  erl_drv_mutex_unlock(*mutex);
#endif
}
Exemple #10
0
void *wxe_main_loop(void *vpdl)
{
  int result; 
  int  argc = 1;
  char * temp = (char *) "Erlang\0";
  char ** argv = &temp;
  ErlDrvPDL pdl = (ErlDrvPDL) vpdl;
  
  driver_pdl_inc_refc(pdl);

  // ErlDrvSysInfo einfo;
  // driver_system_info(&einfo, sizeof(ErlDrvSysInfo));
  // Disable floating point execption if they are on.
  // This should be done in emulator but it's not in yet.
#ifndef _WIN32
  erts_thread_disable_fpe();
#endif
  
  result = wxEntry(argc, argv);
  // fprintf(stderr, "WXWidgets quits main loop %d \r\n", result);
  if(result >= 0 && wxe_status == WXE_INITIATED) {
    /* We are done try to make a clean exit */
    wxe_status = WXE_EXITED;
    driver_pdl_dec_refc(pdl);
    erl_drv_thread_exit(NULL);
    return NULL;
  } else {
    erl_drv_mutex_lock(wxe_status_m);
    wxe_status = WXE_ERROR;
    erl_drv_cond_signal(wxe_status_c);
    erl_drv_mutex_unlock(wxe_status_m);
    driver_pdl_dec_refc(pdl);
    return NULL;    
  }
}
Exemple #11
0
void push_command(int op,char * buf,int len, wxe_data *sd)
{
  /* fprintf(stderr, "Op %d %d [%ld] %d\r\n", op, (int) driver_caller(sd->port_handle),
     wxe_batch->size(), wxe_batch_caller),fflush(stderr); */
  erl_drv_mutex_lock(wxe_batch_locker_m);
  wxe_queue->Add(op, buf, len, sd);

  if(wxe_needs_signal) {
    // wx-thread is waiting on batch end in cond_wait
    erl_drv_cond_signal(wxe_batch_locker_c);
    erl_drv_mutex_unlock(wxe_batch_locker_m);
  } else {
    // wx-thread is waiting gui-events
    erl_drv_mutex_unlock(wxe_batch_locker_m);
    wxWakeUpIdle();
  }
}
Exemple #12
0
void handle_callback_batch(ErlDrvPort port)
{
  WxeApp * app = (WxeApp *) wxTheApp;
  // Should we be able to handle commands when recursing? probably
  erl_drv_mutex_lock(wxe_batch_locker_m);
  app->dispatch(wxe_batch, 0, WXE_CALLBACK);
  wxe_batch_caller = 0;
  erl_drv_mutex_unlock(wxe_batch_locker_m);
}
Exemple #13
0
static void syslogdrv_stop(ErlDrvData handle)
{
    syslogdrv_t* d = (syslogdrv_t*)handle;
    erl_drv_mutex_lock(syslog_mtx);
    closelog();
    erl_drv_mutex_unlock(syslog_mtx);
    if (d->ident) {
        driver_free(d->ident);
    }
    driver_free((char*)handle);
}
Exemple #14
0
static void enqueue_reply(Otp9302AsyncData *adata)
{
    Otp9302MsgQ *msgq = adata->msgq;
    adata->next = NULL;
    adata->refc++;
    erl_drv_mutex_lock(msgq->mtx);
    if (msgq->end)
	msgq->end->next = adata;
    else
	msgq->end = msgq->start = adata;
    msgq->end = adata;
    erl_drv_mutex_unlock(msgq->mtx);
}
Exemple #15
0
void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
{
  WxeApp * app = (WxeApp *) wxTheApp;
  ErlDrvMonitor monitor;
  driver_monitor_process(port, process, &monitor);
  // Should we be able to handle commands when recursing? probably
  erl_drv_mutex_lock(wxe_batch_locker_m);
  //fprintf(stderr, "\r\nCB Start ");fflush(stderr);
  app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
  //fprintf(stderr, ".. done \r\n");fflush(stderr);
  wxe_batch_caller = 0;
  erl_drv_mutex_unlock(wxe_batch_locker_m);
  driver_demonitor_process(port, &monitor);
}
Exemple #16
0
static void dequeue_replies(Otp9302AsyncData *adata)
{
    Otp9302MsgQ *msgq = adata->msgq;
    erl_drv_mutex_lock(msgq->mtx);
    if (--adata->refc == 0)
	driver_free(adata);
    while (msgq->start) {
	send_reply(msgq->start);
	adata = msgq->start;
	msgq->start = msgq->start->next;
	if (--adata->refc == 0)
	    driver_free(adata);
    }
    msgq->start = msgq->end = NULL;
    erl_drv_mutex_unlock(msgq->mtx);
}
Exemple #17
0
void meta_command(int what, wxe_data *sd) {
  if(what == PING_PORT) {
    erl_drv_mutex_lock(wxe_batch_locker_m);
    if(wxe_batch_caller > 0) {
      wxeCommand *Cmd = new wxeCommand(WXE_DEBUG_PING, NULL, 0, sd);
      wxe_batch->Append(Cmd);
      erl_drv_cond_signal(wxe_batch_locker_c);
    }
    wxWakeUpIdle();
    erl_drv_mutex_unlock(wxe_batch_locker_m);
  } else {
    if(sd) {
      wxeMetaCommand Cmd(sd, what);
      wxTheApp->AddPendingEvent(Cmd);
    }
  }
}
Exemple #18
0
static void syslogdrv_output(ErlDrvData handle, char *buf, ErlDrvSizeT len)
{
    syslogdrv_t* d = (syslogdrv_t*)handle;
    /* Incoming data is expected to start with an integer priority encoded
       as a 4-byte integer in network order, therefore make sure there's at
       least 5 bytes in the message. */
    if (d->open && len > 4) {
        int priority = ntohl(*(uint32_t*)buf);
        buf += 4;
        /* re-call openlog in case another instance of the port driver
         * was called in the mean time */
        erl_drv_mutex_lock(syslog_mtx);
        openlog(d->ident, d->logopt, d->facility);
        syslog(priority, "%s", buf);
        erl_drv_mutex_unlock(syslog_mtx);
    }
}
Exemple #19
0
dmessage_t* dthread_recv(dthread_t* thr, dthread_t** source)
{
    dmessage_t* mp;
    
    erl_drv_mutex_lock(thr->iq_mtx);
    if ((mp = thr->iq_front) != NULL) {
	if (!(thr->iq_front = mp->next))
	    thr->iq_rear = NULL;
	thr->iq_len--;
	if (thr->iq_len == 0)
	    dthread_signal_reset(thr);
    }
    erl_drv_mutex_unlock(thr->iq_mtx);

    if (mp && source)
	*source = mp->source;
    return mp;
}
Exemple #20
0
bool WxeApp::OnInit()
{

  global_me = new wxeMemEnv();
  wxe_queue = new wxeFifo(1000);
  wxe_queue_cb_saved = new wxeFifo(200);
  cb_buff = NULL;
  recurse_level = 0;
  delayed_delete = new wxeFifo(10);
  delayed_cleanup  = new wxList;

  wxe_ps_init2();
  // wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED); // Hmm printpreview doesn't work in 2.9 with this

  Connect(wxID_ANY, wxEVT_IDLE,	(wxObjectEventFunction) (wxEventFunction) &WxeApp::idle);
  Connect(CREATE_PORT, wxeEVT_META_COMMAND,(wxObjectEventFunction) (wxEventFunction) &WxeApp::newMemEnv);
  Connect(DELETE_PORT, wxeEVT_META_COMMAND,(wxObjectEventFunction) (wxEventFunction) &WxeApp::destroyMemEnv);
  Connect(WXE_SHUTDOWN, wxeEVT_META_COMMAND,(wxObjectEventFunction) (wxEventFunction) &WxeApp::shutdown);

//   fprintf(stderr, "Size void* %d: long %d long long %d int64 %d \r\n",
// 	  sizeof(void *), sizeof(long), sizeof(long long), sizeof(wxInt64));
  initEventTable();
  wxInitAllImageHandlers();

#ifdef  _MACOSX
  /* Create a default MenuBar so that we can intercept the quit command */
  wxMenuBar *macMB = new wxMenuBar;
  wxMenuBar::MacSetCommonMenuBar(macMB);
  macMB->MacInstallMenuBar();
  macMB->Connect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED,
		 (wxObjectEventFunction) (wxEventFunction) &WxeApp::dummy_close);
#endif

  SetExitOnFrameDelete(false);

  init_nonconsts(global_me, init_caller);
  erl_drv_mutex_lock(wxe_status_m);
  wxe_status = WXE_INITIATED;
  erl_drv_cond_signal(wxe_status_c);
  erl_drv_mutex_unlock(wxe_status_m);
  return TRUE;
}
Exemple #21
0
void meta_command(int what, wxe_data *sd) {
  if(what == PING_PORT && wxe_status == WXE_INITIATED) {
    erl_drv_mutex_lock(wxe_batch_locker_m);
    if(wxe_needs_signal) {
      wxe_queue->Add(WXE_DEBUG_PING, NULL, 0, sd);
      erl_drv_cond_signal(wxe_batch_locker_c);
    }
    wxWakeUpIdle();
    erl_drv_mutex_unlock(wxe_batch_locker_m);
  } else {
    if(sd && wxe_status == WXE_INITIATED) {
      wxeMetaCommand Cmd(sd, what);
      wxTheApp->AddPendingEvent(Cmd);
      if(what == DELETE_PORT) {
	driver_free(sd->bin);
	free(sd);
      }
    }
  }
}
Exemple #22
0
void push_command(int op,char * buf,int len, wxe_data *sd) 
{  
  // fprintf(stderr, "Op %d %d\r\n", op, (int) driver_caller(sd->port)),fflush(stderr);
  wxeCommand *Cmd = new wxeCommand(op, buf, len, sd);
  erl_drv_mutex_lock(wxe_batch_locker_m);
  wxe_batch->Append(Cmd);
  
  if(wxe_batch_caller > 0) {
    // wx-thread is waiting on batch end in cond_wait
    erl_drv_cond_signal(wxe_batch_locker_c);
  } else {
    // wx-thread is waiting gui-events
    if(op == WXE_BATCH_BEGIN) {
      wxe_batch_caller = 1;
    }
    erl_drv_cond_signal(wxe_batch_locker_c);
    wxWakeUpIdle();
  }  
  erl_drv_mutex_unlock(wxe_batch_locker_m);
}
Exemple #23
0
void *wxe_main_loop(void *vpdl)
{
    int result;
    int  argc = 1;
    char * temp = (char *) "Erlang";
    char * argv[] = {temp,NULL};
    ErlDrvPDL pdl = (ErlDrvPDL) vpdl;

    driver_pdl_inc_refc(pdl);

    // Disable floating point execption if they are on.
    // This should be done in emulator but it's not in yet.
#ifndef _WIN32
    erts_thread_disable_fpe();
#else
    // Setup that wxWidgets should look for cursors and icons in
    // this dll and not in werl.exe (which is the default)
    HMODULE WXEHandle = GetModuleHandle(_T("wxe_driver"));
    wxSetInstance((HINSTANCE) WXEHandle);
#endif

    wxe_ps_init();
    result = wxEntry(argc, argv);
    // fprintf(stderr, "WXWidgets quits main loop %d \r\n", result);
    if(result >= 0 && wxe_status == WXE_INITIATED) {
        /* We are done try to make a clean exit */
        wxe_status = WXE_EXITED;
        driver_pdl_dec_refc(pdl);
#ifndef __DARWIN__
        erl_drv_thread_exit(NULL);
#endif
        return NULL;
    } else {
        erl_drv_mutex_lock(wxe_status_m);
        wxe_status = WXE_ERROR;
        erl_drv_cond_signal(wxe_status_c);
        erl_drv_mutex_unlock(wxe_status_m);
        driver_pdl_dec_refc(pdl);
        return NULL;
    }
}
Exemple #24
0
int dthread_send(dthread_t* thr, dthread_t* source, dmessage_t* mp)
{
    dmessage_t* mr;
    int len;
    int r = 0;

    erl_drv_mutex_lock(thr->iq_mtx);

    mp->next = NULL;
    mp->source = source;

    if ((mr = thr->iq_rear) != NULL)
	mr->next = mp;
    else
	thr->iq_front = mp;
    thr->iq_rear = mp;
    len = ++thr->iq_len;
    if (len == 1)
	r = dthread_signal_set(thr);
    erl_drv_mutex_unlock(thr->iq_mtx);
    DEBUGF("dthread_send: iq_len=%d", len);
    return r;
}
Exemple #25
0
static void* innostore_worker(void* arg)
{
    PortState* state = (PortState*)arg;
    erl_drv_mutex_lock(state->worker_lock);
    while (1)
    {
        //
        // NOTE: Holds the worker lock for the duration of the loop !!
        //
        if (state->shutdown_flag)
        {
            driver_free(state->work_buffer);
            state->work_buffer = 0;
            if (state->op != 0)
            {
                send_error_atom(state, "stopping");
                state->op = 0;
            }
            erl_drv_cond_signal(state->worker_cv);
            erl_drv_mutex_unlock(state->worker_lock);
            break;
        }

        if (state->op)
        {
            state->op(state);
            state->op = 0;
            driver_free(state->work_buffer);
            state->work_buffer = 0;
        }
        else
        {
            erl_drv_cond_wait(state->worker_cv, state->worker_lock);
        }
    }
    return 0;
}
Exemple #26
0
int
erts_mutex_unlock(erl_mutex_t mtx)
{
    erl_drv_mutex_unlock((ErlDrvMutex *) mtx);
    return 0;
}
Exemple #27
0
void enif_mutex_unlock(ErlNifMutex *mtx) { erl_drv_mutex_unlock(mtx); }
Exemple #28
0
int dthread_poll(dthread_t* thr, dthread_poll_event_t* events, size_t* nevents, 
		 int timeout)
{
    struct timeval tm;
    struct timeval* tp;
    fd_set readfds;
    fd_set writefds;
    fd_set errorfds;
    int fd,nfds = 0;
    int ready;
    int i,n,iq_len=0;

    if (timeout < 0)
	tp = NULL;
    else {
	tm.tv_sec = timeout / 1000;
	tm.tv_usec = (timeout - tm.tv_sec*1000) * 1000;
	tp = &tm;
    }
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_ZERO(&errorfds);

    if ((fd = DTHREAD_EVENT(thr->iq_signal[0])) >= 0) {
	FD_SET(fd, &readfds);
	FD_SET(fd, &errorfds);
	DEBUGF("FD_SET: iq_signal[0] = %d", fd);
	if (fd > nfds) nfds = fd;
    }

    if (events && nevents && *nevents) {
	n = (int) (*nevents);
	for (i = 0; i < n; i++) {
	    events[i].revents = 0;  // clear here in case of timeout etc
	    if (events[i].events) {
		fd = DTHREAD_EVENT(events[i].event);
		if (events[i].events & ERL_DRV_READ) {
		    FD_SET(fd, &readfds);
		    FD_SET(fd, &errorfds);
		}
		if (events[i].events & ERL_DRV_WRITE)
		    FD_SET(fd, &writefds);
		if (fd > nfds) nfds = fd;
	    }
	}
    }

    DEBUGF("select nfds=%d, tp=%p", nfds, tp);
    ready = select(nfds+1, &readfds, &writefds, &errorfds, tp);
    DEBUGF("select result r=%d", ready);
    if (ready <= 0) {
	if (nevents)
	    *nevents = 0;
	return ready;
    }

    // check queue !
    fd = DTHREAD_EVENT(thr->iq_signal[0]);
    if (FD_ISSET(fd, &readfds)) {
	erl_drv_mutex_lock(thr->iq_mtx);
	iq_len = thr->iq_len;
	erl_drv_mutex_unlock(thr->iq_mtx);
	ready--;
    }

    // check io events
    if (ready && events && nevents && *nevents) {
	size_t nready = 0;
	n = (int) (*nevents);
	for (i = 0; ready && (i < n); i++) {
	    size_t fd_ready = 0;
	    fd = DTHREAD_EVENT(events[i].event);
	    if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds)) {
		events[i].revents |= ERL_DRV_READ;
		if (FD_ISSET(fd, &errorfds))
		    events[i].revents |= ERL_DRV_EXCEP;
		fd_ready = 1;
	    }
	    if (FD_ISSET(fd, &writefds)) {
		events[i].revents |= ERL_DRV_WRITE; 
		fd_ready = 1;
	    }
	    nready += fd_ready;
	    ready--;
	}
	*nevents = nready;
    }
    return iq_len;
}
Exemple #29
0
static void do_set_cfg(void* arg)
{
    PortState* state = (PortState*)arg;

    erl_drv_mutex_lock(G_ENGINE_STATE_LOCK);
    if (G_ENGINE_STATE == ENGINE_STOPPED)
    {
        char* key   = UNPACK_STRING(state->work_buffer, 0);
        const char* value = UNPACK_STRING(state->work_buffer, strlen(key)+1);

        if (strcmp(key, "error_log") == 0)
        {
            if (set_log_file(value) == 0)
            {
                send_ok(state);
            }
            else
            {
                send_error_atom(state, "einval");
            }
        }
        else
        {
            // Check the expected type of the provided key so as to 1. validate it's a good key
            // and 2. know what setter to use.
            ib_cfg_type_t key_type;
            ib_err_t error = ib_cfg_var_get_type(key, &key_type);
            if (error == DB_SUCCESS)
            {
                if (key_type == IB_CFG_TEXT)
                {
                    // HACK: Semantics of setting a text configuration value for innodb changed
                    // to be pointer assignment (from copy) for vsn 1.0.6.6750. So, we strdup the
                    // value to ensure everything works as expected.
                    // TODO: Setup some sort of list of strdup'd values to ensure they all get
                    // cleaned up properly. In typical usage, this isn't going to be a problem
                    // as you only initialize once per run, but it bothers me just the same.
                    error = ib_cfg_set(key, strdup(value));
                }
                else
                {
                    ErlDrvUInt value_i;
                    UNPACK_INT(state->work_buffer, strlen(key)+1, &value_i);
                    error = ib_cfg_set(key, value_i);
                }

            }

            if (error == DB_SUCCESS)
            {
                send_ok(state);
            }
            else
            {
                send_error_str(state, ib_strerror(error));
            }
        }
    }
    else
    {
        send_error_atom(state, "starting");
    }

    erl_drv_mutex_unlock(G_ENGINE_STATE_LOCK);
}
Exemple #30
0
static int innostore_drv_control(ErlDrvData handle, unsigned int cmd,
                              char* inbuf, int inbuf_sz,
                              char** outbuf, int outbuf_sz)
{
    PortState* state = (PortState*)handle;

    // Grab the worker lock.
    erl_drv_mutex_lock(state->worker_lock);

    assert(state->op == 0);

    // Verify that caller is not attempting cursor operation when no cursor is
    // active (or vice-versa)
    if (state->port_state == STATE_READY && is_cmd(CMD_CURSOR_OPS))
    {
        erl_drv_mutex_unlock(state->worker_lock);
        send_error_atom(state, "cursor_not_open");
        return 0;
    }
    else if (state->port_state == STATE_CURSOR && !is_cmd(CMD_CURSOR_OPS))
    {
        erl_drv_mutex_unlock(state->worker_lock);
        send_error_atom(state, "cursor_is_open");
        return 0;
    }

    // Copy inbuf into our work buffer
    if (inbuf_sz > 0)
    {
        state->work_buffer = driver_alloc(inbuf_sz);
        memcpy(state->work_buffer, inbuf, inbuf_sz);
    }

    // Select the appropriate async op
    switch (cmd)
    {
    case CMD_SET_CFG:
        state->op = &do_set_cfg;
        break;

    case CMD_START:
        state->op = &do_start;
        break;

    case CMD_INIT_TABLE:
        state->op = &do_init_table;
        break;

    case CMD_IS_STARTED:
        // Check the global state -- prior to doing that, release our worker lock
        // so as to avoid weird locking overlaps. Store the true/false value as
        // a single byte in outbuf. No need to do any allocation as the VM always
        // provides a 64-byte outbuf buffer by default.
        assert(outbuf_sz > 0);
        erl_drv_mutex_unlock(state->worker_lock);
        erl_drv_mutex_lock(G_ENGINE_STATE_LOCK);
        (*outbuf)[0] = (G_ENGINE_STATE == ENGINE_STARTED);
        erl_drv_mutex_unlock(G_ENGINE_STATE_LOCK);
        return 1;

    case CMD_GET:
        state->op = &do_get;
        break;

    case CMD_PUT:
        state->op = &do_put;
        break;

    case CMD_DELETE:
        state->op = &do_delete;
        break;

    case CMD_LIST_TABLES:
        state->op = &do_list_tables;
        break;

    case CMD_CURSOR_OPEN:
        state->op = &do_cursor_open;
        break;

    case CMD_CURSOR_MOVE:
        state->op = &do_cursor_move;
        break;

    case CMD_CURSOR_CLOSE:
        state->op = &do_cursor_close;
        break;

    case CMD_DROP_TABLE:
        state->op = &do_drop_table;
        break;

    case CMD_STATUS:
        state->op = &do_status;
        break;
    }

    // Signal the worker
    erl_drv_cond_signal(state->worker_cv);
    erl_drv_mutex_unlock(state->worker_lock);
    *outbuf = 0;
    return 0;
}