Beispiel #1
0
static unsigned long _stdcall
thread_start_func_1(void *th_ptr)
{
    rb_thread_t *th = th_ptr;
    volatile HANDLE thread_id = th->thread_id;

    native_thread_init_stack(th);
/*    th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);

    if ( !th->native_thread_data.interrupt_event)
    {
        DWORD dwErr = GetLastError();
        thread_debug("thread interrupt_event error: %d\n", dwErr );
    }
*/

    /* run */
    thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th,
		 th->thread_id, th->native_thread_data.interrupt_event);

    thread_start_func_2(th, th->machine_stack_start, rb_ia64_bsp());

    w32_close_handle(thread_id);
    thread_debug("thread deleted (th: %p)\n", th);
    return 0;
}
Beispiel #2
0
static int
native_thread_create(rb_thread_t *th)
{
    size_t stack_size = 4 * 1024; /* 4KB */

    th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);

    if ( !th->native_thread_data.interrupt_event)
    {
        DWORD dwErr = GetLastError();
        thread_debug("thread interrupt_event error: %d\n", dwErr );
    }

    th->thread_id = w32_create_thread(stack_size, thread_start_func_1, th);

    if ((th->thread_id) == 0) {
	    st_delete_wrap(th->vm->living_threads, th->self);

        if ( th->native_thread_data.interrupt_event )
            w32_close_handle(th->native_thread_data.interrupt_event);

	    rb_raise(rb_eThreadError, "can't create Thread (%d)", errno);
    }

    w32_resume_thread(th->thread_id);

    if (THREAD_DEBUG) {
	Sleep(0);
	thread_debug("create: (th: %p, thid: %p, intr: %p), stack size: %d\n",
		     th, th->thread_id,
		     th->native_thread_data.interrupt_event, stack_size);
    }
    return 0;
}
Beispiel #3
0
static int
__cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, unsigned long msec)
{
    DWORD r;
    struct cond_event_entry entry;
    struct cond_event_entry *head = (struct cond_event_entry*)cond;

    entry.event = CreateEvent(0, FALSE, FALSE, 0);

    /* cond is guarded by mutex */
    entry.next = head;
    entry.prev = head->prev;
    head->prev->next = &entry;
    head->prev = &entry;

    native_mutex_unlock(mutex);
    {
	r = WaitForSingleObject(entry.event, msec);
	if ((r != WAIT_OBJECT_0) && (r != WAIT_TIMEOUT)) {
	    rb_bug("native_cond_wait: WaitForSingleObject returns %lu", r);
	}
    }
    native_mutex_lock(mutex);

    entry.prev->next = entry.next;
    entry.next->prev = entry.prev;

    w32_close_handle(entry.event);
    return (r == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
}
Beispiel #4
0
static void
native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex)
{
    DWORD r;
    struct cond_event_entry entry;

    entry.next = 0;
    entry.event = CreateEvent(0, FALSE, FALSE, 0);

    /* cond is guarded by mutex */
    if (cond->next) {
	cond->last->next = &entry;
	cond->last = &entry;
    }
    else {
	cond->next = &entry;
	cond->last = &entry;
    }

    native_mutex_unlock(mutex);
    {
	r = WaitForSingleObject(entry.event, INFINITE);
	if (r != WAIT_OBJECT_0) {
	    rb_bug("native_cond_wait: WaitForSingleObject returns %lu", r);
	}
    }
    native_mutex_lock(mutex);

    w32_close_handle(entry.event);
}
Beispiel #5
0
static int
native_thread_create(rb_thread_t *th)
{
    size_t stack_size = 4 * 1024; /* 4KB */
//RHO
    th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);

    if ( !th->native_thread_data.interrupt_event)
    {
        DWORD dwErr = GetLastError();
        thread_debug("thread interrupt_event error: %d\n", dwErr );
    }
//RHO
    th->thread_id = w32_create_thread(stack_size, thread_start_func_1, th);

    if ((th->thread_id) == 0) {
//RHO
		if ( th->native_thread_data.interrupt_event )
            w32_close_handle(th->native_thread_data.interrupt_event);
//RHO				
		return thread_errno;
    }

    w32_resume_thread(th->thread_id);

    if (THREAD_DEBUG) {
	Sleep(0);
	thread_debug("create: (th: %p, thid: %p, intr: %p), stack size: %d\n",
		     th, th->thread_id,
		     th->native_thread_data.interrupt_event, stack_size);
    }
    return 0;
}
Beispiel #6
0
static void
native_thread_destroy(rb_thread_t *th)
{
    HANDLE intr = InterlockedExchangePointer(&th->native_thread_data.interrupt_event, 0);
    thread_debug("close handle - intr: %p, thid: %p\n", intr, th->thread_id);
    w32_close_handle(intr);
}
Beispiel #7
0
static void
close_proc_handle(void)
{
    TRACE(("close_proc_handle %#x\n", proc_handle));
    (void) w32_close_handle(proc_handle);
    proc_handle = BAD_PROC_HANDLE;
}
Beispiel #8
0
static HANDLE
exec_shell(char *cmd, HANDLE *handles, int hide_child)
{
    W32_CHAR             *w32_cmdstr = 0;
    char                 *cmdstr;
    int                  freestr;
    PROCESS_INFORMATION  pi;
    STARTUPINFO          si;

    proc_handle = BAD_PROC_HANDLE;  /* in case of failure */
    TRACE((T_CALLED "exec_shell %s\n", cmd));
    if ((cmdstr = mk_shell_cmd_str(cmd, &freestr, TRUE)) == NULL)
    {
        /* heap exhausted! */

        no_memory("exec_shell");

        /* Give user a chance to read message--more will surely follow. */
        Sleep(3000);
    } else if ((w32_cmdstr = w32_charstring(cmdstr)) == 0) {
        no_memory("exec_shell");
    } else {

        memset(&si, 0, sizeof(si));
        si.cb          = sizeof(si);
        si.dwFlags     = STARTF_USESTDHANDLES;
        si.hStdInput   = handles[0];
        si.hStdOutput  = handles[1];
        si.hStdError   = handles[2];
#if DISP_NTWIN
        if (hide_child)
        {
            si.dwFlags     |= STARTF_USESHOWWINDOW;
            si.wShowWindow  = SW_HIDE;
        }
#endif
        TRACE(("CreateProcess %s (pipe)\n", cmdstr));
        if (CreateProcess(NULL,
                          w32_cmdstr,
                          NULL,
                          NULL,
                          TRUE,       /* Inherit handles */
                          0,
                          NULL,
                          NULL,
                          &si,
                          &pi))
        {
            /* Success */

            w32_close_handle(pi.hThread);
            proc_handle = pi.hProcess;
            TRACE(("...created proc_handle %#x\n", proc_handle));
        }
    }
    FreeIfNeeded(cmdstr);
    FreeIfNeeded(w32_cmdstr);
    returnPtr(proc_handle);
}
Beispiel #9
0
static void
native_thread_destroy(rb_thread_t *th)
{
    HANDLE intr = th->native_thread_data.interrupt_event;
    thread_debug("close handle - intr: %p, thid: %p\n", intr, th->thread_id);
    th->native_thread_data.interrupt_event = 0;
    w32_close_handle(intr);
}
Beispiel #10
0
void
native_mutex_destroy(rb_thread_lock_t *lock)
{
#if USE_WIN32_MUTEX
    w32_close_handle(lock);
#else
    DeleteCriticalSection(lock);
#endif
}
Beispiel #11
0
static unsigned long _stdcall
thread_start_func_1(void *th_ptr)
{
    rb_thread_t *th = th_ptr;
    VALUE stack_start;
    volatile HANDLE thread_id = th->thread_id;

    th->native_thread_data.interrupt_event = CreateEvent(0, TRUE, FALSE, 0);

    /* run */
    thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th,
		 th->thread_id, th->native_thread_data.interrupt_event);
    thread_start_func_2(th, &stack_start, 0);

    w32_close_handle(thread_id);
    thread_debug("thread deleted (th: %p)\n", th);
    return 0;
}
Beispiel #12
0
static void
native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex)
{
    DWORD r;
    struct cond_event_entry entry;
//RHO	
    //WinMo BUG: in release mode CreateEventW without name inside non-main thread does not work
    static int nCounter = 0;
    wchar_t buf[20];
    wsprintfW(buf, L"REvent%d", nCounter);
    nCounter = nCounter + 1;

    entry.next = 0;
    entry.event = CreateEventW(0, FALSE, FALSE, buf);
//RHO

    /* cond is guarded by mutex */
    if (cond->next) {
	cond->last->next = &entry;
	cond->last = &entry;
    }
    else {
	cond->next = &entry;
	cond->last = &entry;
    }

    native_mutex_unlock(mutex);
    {
	r = WaitForSingleObject(entry.event, INFINITE);
	if (r != WAIT_OBJECT_0) {
	    rb_bug("native_cond_wait: WaitForSingleObject returns %lu", r);
	}
    }
    native_mutex_lock(mutex);

    w32_close_handle(entry.event);
}
Beispiel #13
0
static int
native_inout_popen(FILE **fr, FILE **fw, char *cmd)
{
    char   buf[NFILEN + 128];
    HANDLE handles[3];
    int    i, rc, rp[3], tmpin_fd, wp[3];

    TRACE((T_CALLED "native_inout_popen cmd=%s\n", cmd));
    proc_handle   = BAD_PROC_HANDLE;
    rp[0] = rp[1] = rp[2] = wp[0] = wp[1] = wp[2] = BAD_FD;
    handles[0]    = handles[1] = handles[2] = INVALID_HANDLE_VALUE;
    tmpin_fd      = BAD_FD;
    tmpin_name    = NULL;
    set_console_title(cmd);
    if (is_win95())
    {
        char *cmdp;

        /*
         * If w32pipes is set on a win95 host, you don't ever want slowreadf()
         * to periodically update the display while an intrinisic, high
         * bandwidth DOS command is in progress.  Reason:  the win95 shell,
         * command.com, will simply hang in the following scenario:
         *
         *    ^X!<high_bandwidth_cmd>
         *
         *         and
         *
         *    PIPESIZ < output of <high_bandwidth_cmd>
         *
         * I'm assuming that what's going on here is that command.com is
         * written in ASM and is using very low level BIOS/DOS calls to
         * effect output and, furthermore, that these low level calls don't
         * block when the input consumer is busy.
         */

        cmdp = skip_blanks(cmd);
        nowait_pipe_cmd = (strnicmp(cmdp, "dir", 3) == 0)  ||
                          (strnicmp(cmdp, "type", 4) == 0);
    }
    do
    {
        if (fr)
        {
            *fr = NULL;

            /*
             * Open (parent's) input pipe in TEXT mode, which will force
             * translation of the child's CR/LF record delimiters to NL
             * and keep the dreaded ^M chars from temporarily appearing
             * in a vile buffer (ugly).
             */
            if (_pipe(rp, PIPESIZ, O_TEXT|O_NOINHERIT) == -1)
                break;
            if ((rp[2] = _dup(rp[1])) == -1)
                break;
            handles[2] = handles[1] = (HANDLE) _get_osfhandle(rp[2]);
            (void) close(rp[1]);
            rp[1] = BAD_FD;
            if (! fw)
            {
                /*
                 * This is a read pipe (only).  Connect child's stdin to
                 * an empty file.  Under no circumstances should the
                 * child's stdin be connected to a device (else lots of
                 * screwy things will occur).  In particular, connecting
                 * the child's stdin to the parent's stdin will cause
                 * aborts and hangs on the various Win32 hosts.  You've
                 * been warned.
                 */

                if ((tmpin_name = _tempnam(getenv("TEMP"), "vile")) == NULL)
                    break;
                if ((tmpin_fd = open(tmpin_name,
                                     O_RDONLY|O_CREAT|O_TRUNC,
                                     _S_IWRITE|_S_IREAD)) == BAD_FD)
                {
                    break;
                }
                handles[0] = (HANDLE) _get_osfhandle(tmpin_fd);
            }
            if ((*fr = fdopen(rp[0], "r")) == 0)
                break;
        }
        if (fw)
        {
            *fw = NULL;

            /*
             * Open (child's) output pipe in binary mode, which will
             * prevent translation of the parent's CR/LF record delimiters
             * to NL.  Apparently, many apps want those delimiters :-) .
             */
            if (_pipe(wp, PIPESIZ, O_BINARY|O_NOINHERIT) == -1)
                break;
            if ((wp[2] = _dup(wp[0])) == -1)
                break;
            handles[0] = (HANDLE)_get_osfhandle(wp[2]);
            (void) close(wp[0]);
            wp[0] = BAD_FD;
            if (! fr)
                handles[1] = handles[2] = GetStdHandle(STD_OUTPUT_HANDLE);
            if ((*fw = fdopen(wp[1], "w")) == 0)
                break;
        }
        rc = (exec_shell(cmd,
                         handles,
                         fr != NULL  /* Child wdw hidden unless write pipe. */
                        ) == BAD_PROC_HANDLE) ? FALSE : TRUE;
        if (fw)
        {
            if (! rc)
            {
                /* Shell process failed, put complaint in user's face. */

                sprintf(buf, SHELL_ERR_MSG, get_shell());
                lastditch_msg(buf);
            }
            w32_close_handle(handles[0]);
        }
        if (fr)
        {
            if (! rc)
            {
                unsigned len;

                /*
                 * Shell process failed, put complaint in user's buffer.
                 * Can't write to handles[1] on a win2k host because the
                 * previously failed CreateProcess() call damaged the
                 * handle.
                 */
                len = (unsigned) (lsprintf(buf, SHELL_ERR_MSG, get_shell()) - buf);
                (void) write(rp[2], buf, len);
                (void) close(rp[2]);   /* in weird state; why not? */
            }
            w32_close_handle(handles[1]);
            close_fd(tmpin_fd);
        }
        returnCode(rc);
    }
    while (FALSE);

    /* If we get here -- some operation has failed.  Clean up. */

    close_fd(wp[0]);
    close_fd(wp[1]);
    close_fd(wp[2]);
    close_fd(rp[0]);
    close_fd(rp[1]);
    close_fd(rp[2]);
    close_fd(tmpin_fd);
    for (i = 0; i < 3; i++)
    {
        if (handles[i] != INVALID_HANDLE_VALUE)
            w32_close_handle(handles[i]);
    }
    common_cleanup();
    returnCode(FALSE);
}