Exemplo n.º 1
0
Arquivo: sys.c Projeto: weisslj/otp
void
erts_sys_main_thread(void)
{
    erts_thread_disable_fpe();
#ifdef __DARWIN__
    initialize_darwin_main_thread_pipes();
#endif
    /* Become signal receiver thread... */
#ifdef ERTS_ENABLE_LOCK_CHECK
    erts_lc_set_thread_name("signal_receiver");
#endif

    smp_sig_notify(0); /* Notify initialized */

    /* Wait for a signal to arrive... */

#ifdef __DARWIN__
    while (1) {
	/*
	 * The wx driver needs to be able to steal the main thread for Cocoa to
	 * work properly.
	 */
	fd_set readfds;
	int res;

	FD_ZERO(&readfds);
	FD_SET(erts_darwin_main_thread_pipe[0], &readfds);
	res = select(erts_darwin_main_thread_pipe[0] + 1, &readfds, NULL, NULL, NULL);
	if (res > 0 && FD_ISSET(erts_darwin_main_thread_pipe[0],&readfds)) {
	    void* (*func)(void*);
	    void* arg;
	    void *resp;
            res = read(erts_darwin_main_thread_pipe[0],&func,sizeof(void* (*)(void*)));
            if (res != sizeof(void* (*)(void*)))
                break;
            res = read(erts_darwin_main_thread_pipe[0],&arg,sizeof(void*));
            if (res != sizeof(void*))
                break;
	    resp = (*func)(arg);
	    write(erts_darwin_main_thread_result_pipe[1],&resp,sizeof(void *));
	}

        if (res == -1 && errno != EINTR)
            break;
    }
    /* Something broke with the main thread pipe, so we ignore it for now.
       Most probably erts has closed this pipe and is about to exit. */
#endif /* #ifdef __DARWIN__ */

    while (1) {
#ifdef DEBUG
	int res =
#else
	(void)
#endif
	    select(0, NULL, NULL, NULL, NULL);
	ASSERT(res < 0);
	ASSERT(errno == EINTR);
    }
}
Exemplo n.º 2
0
Arquivo: sys.c Projeto: weisslj/otp
static void *
signal_dispatcher_thread_func(void *unused)
{
#ifdef ERTS_ENABLE_LOCK_CHECK
    erts_lc_set_thread_name("signal_dispatcher");
#endif
    while (1) {
        union {int signum; char buf[4];} sb;
        Eterm signal;
	int res, i = 0;
	/* Block on read() waiting for a signal notification to arrive... */

        do {
            res = read(sig_notify_fds[0], (void *) &sb.buf[i], sizeof(int) - i);
            i += res > 0 ? res : 0;
        } while ((i < sizeof(int) && res >= 0) || (res < 0 && errno == EINTR));

	if (res < 0) {
	    erts_exit(ERTS_ABORT_EXIT,
		     "signal-dispatcher thread got unexpected error: %s (%d)\n",
		     erl_errno_id(errno),
		     errno);
	}
        /*
         * NOTE 1: The signal dispatcher thread should not do work
         *         that takes a substantial amount of time (except
         *         perhaps in test and debug builds). It needs to
         *         be responsive, i.e, it should only dispatch work
         *         to other threads.
         *
         * NOTE 2: The signal dispatcher thread is not a blockable
         *         thread (i.e., not a thread managed by the
         *         erl_thr_progress module). This is intentional.
         *         We want to be able to interrupt writing of a crash
         *         dump by hitting C-c twice. Since it isn't a
         *         blockable thread it is important that it doesn't
         *         change the state of any data that a blocking thread
         *         expects to have exclusive access to (unless the
         *         signal dispatcher itself explicitly is blocking all
         *         blockable threads).
         */
        switch (sb.signum) {
            case 0: continue;
            case SIGINT:
                break_requested();
                break;
            default:
                if ((signal = signum_to_signalterm(sb.signum)) == am_error) {
                    erts_exit(ERTS_ABORT_EXIT,
                            "signal-dispatcher thread received unknown "
                            "signal notification: '%d'\n",
                            sb.signum);
                }
                signal_notify_requested(signal);
        }
        ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
    }
    return NULL;
}
Exemplo n.º 3
0
static void* async_main(void* arg)
{
    AsyncQueue* q = (AsyncQueue*) arg;

#ifdef ERTS_ENABLE_LOCK_CHECK
    {
        char buf[27];
        erts_snprintf(&buf[0], 27, "async %d", q->no);
        erts_lc_set_thread_name(&buf[0]);
    }
#endif

    while(1) {
        ErlAsync* a = async_get(q);

        if (a->port == NIL) { /* TIME TO DIE SIGNAL */
            erts_free(ERTS_ALC_T_ASYNC, (void *) a);
            break;
        }
        else {
            (*a->async_invoke)(a->async_data);
            /* Major problem if the code for async_invoke
               or async_free is removed during a blocking operation */
#ifdef ERTS_SMP
            {
                Port *p;
                p = erts_id2port_sflgs(a->port,
                                       NULL,
                                       0,
                                       ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
                if (!p) {
                    if (a->async_free)
                        (*a->async_free)(a->async_data);
                }
                else {
                    if (async_ready(p, a->async_data)) {
                        if (a->async_free)
                            (*a->async_free)(a->async_data);
                    }
                    async_detach(a->hndl);
                    erts_port_release(p);
                }
                if (a->pdl) {
                    driver_pdl_dec_refc(a->pdl);
                }
                erts_free(ERTS_ALC_T_ASYNC, (void *) a);
            }
#else
            if (a->pdl) {
                driver_pdl_dec_refc(a->pdl);
            }
            erts_mtx_lock(&async_ready_mtx);
            a->next = async_ready_list;
            async_ready_list = a;
            erts_mtx_unlock(&async_ready_mtx);
            sys_async_ready(q->hndl);
#endif
        }
    }

    return NULL;
}