static void async_add(ErlAsync* a, AsyncQueue* q) { /* XXX:PaN Is this still necessary when ports lock drivers? */ if (is_internal_port(a->port)) { ERTS_LC_ASSERT(erts_drvportid2port(a->port)); /* make sure the driver will stay around */ driver_lock_driver(internal_port_index(a->port)); } erts_mtx_lock(&q->mtx); if (q->len == 0) { q->head = a; q->tail = a; q->len = 1; erts_cnd_signal(&q->cv); } else { /* no need to signal (since the worker is working) */ a->next = q->head; q->head->prev = a; q->head = a; q->len++; } erts_mtx_unlock(&q->mtx); }
static erts_tse_t *async_thread_init(ErtsAsyncQ *aq) { ErtsThrQInit_t qinit = ERTS_THR_Q_INIT_DEFAULT; erts_tse_t *tse = erts_tse_fetch(); #ifdef ERTS_SMP ErtsThrPrgrCallbacks callbacks; callbacks.arg = (void *) tse; callbacks.wakeup = async_wakeup; callbacks.prepare_wait = NULL; callbacks.wait = NULL; erts_thr_progress_register_unmanaged_thread(&callbacks); #endif qinit.live.queue = ERTS_THR_Q_LIVE_LONG; qinit.live.objects = ERTS_THR_Q_LIVE_SHORT; qinit.arg = (void *) tse; qinit.notify = async_wakeup; #if ERTS_USE_ASYNC_READY_Q qinit.auto_finalize_dequeue = 0; #endif erts_thr_q_initialize(&aq->thr_q, &qinit); /* Inform main thread that we are done initializing... */ erts_mtx_lock(&async->init.data.mtx); async->init.data.no_initialized++; erts_cnd_signal(&async->init.data.cnd); erts_mtx_unlock(&async->init.data.mtx); return tse; }