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; }
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; }
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; }
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); }
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; }
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); }
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; }
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); }
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); }
void native_mutex_destroy(rb_thread_lock_t *lock) { #if USE_WIN32_MUTEX w32_close_handle(lock); #else DeleteCriticalSection(lock); #endif }
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; }
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); }
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); }