From 0c565ab35b47c29c0d5ba7a6e28ca63535776ce8 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sun, 16 May 2004 04:18:50 +0000 Subject: [PATCH] * cygthread.cc (cygthread::is): Eliminate. * cygthread.h (cygthread::is): Eliminate declaratin. * fhandler_console.cc (fhandler_console::read): Only wait for signal_arrived in the main thread. * fhandler_socket.cc: Include new "wininfo.h". (fhandler_socket::ioctl): Use 'winmsg' rather than 'gethwnd()'. * sync.cc (muto::grab): Define new function. (muto::acquire): Use tls pointer rather than tid. (muto::acquired): Ditto. (muto::reset): Delete. (muto::release): Ditto. Also implement "close on last release". * sync.h (muto::tid): Delete. (muto::tls): New field. (muto::ismine): Delete. (muto::owner): Delete. (muto::unstable): Delete. (muto::reset): Delete. (muto::upforgrabs): New method. (muto::grab): Ditto. (new_muto_name): New define. * wininfo.h: New file. (wininfo): New class. * window.cc: Rework throughout to use winfo class for controlling invisible window operation. (gethwnd): Delete definition. * winsup.h (gethwnd): Delete declaration. --- winsup/cygwin/ChangeLog | 29 +++++++ winsup/cygwin/cygthread.cc | 12 --- winsup/cygwin/cygthread.h | 1 - winsup/cygwin/fhandler_console.cc | 3 +- winsup/cygwin/fhandler_socket.cc | 7 +- winsup/cygwin/sync.cc | 55 +++++++------ winsup/cygwin/sync.h | 18 +++-- winsup/cygwin/window.cc | 125 ++++++++++++++++++------------ winsup/cygwin/winsup.h | 2 - 9 files changed, 150 insertions(+), 102 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f0a607908..2be855855 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,32 @@ +2004-05-15 Christopher Faylor + + * cygthread.cc (cygthread::is): Eliminate. + * cygthread.h (cygthread::is): Eliminate declaratin. + * fhandler_console.cc (fhandler_console::read): Only wait for + signal_arrived in the main thread. + * fhandler_socket.cc: Include new "wininfo.h". + (fhandler_socket::ioctl): Use 'winmsg' rather than 'gethwnd()'. + * sync.cc (muto::grab): Define new function. + (muto::acquire): Use tls pointer rather than tid. + (muto::acquired): Ditto. + (muto::reset): Delete. + (muto::release): Ditto. Also implement "close on last release". + * sync.h (muto::tid): Delete. + (muto::tls): New field. + (muto::ismine): Delete. + (muto::owner): Delete. + (muto::unstable): Delete. + (muto::reset): Delete. + (muto::upforgrabs): New method. + (muto::grab): Ditto. + (new_muto_name): New define. + * wininfo.h: New file. + (wininfo): New class. + * window.cc: Rework throughout to use winfo class for controlling + invisible window operation. + (gethwnd): Delete definition. + * winsup.h (gethwnd): Delete declaration. + 2004-05-15 Christopher Faylor * cygheap.h: Remove some parameter names from declarations throughout. diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index d655640e0..7ad860b45 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -101,18 +101,6 @@ cygthread::init () main_thread_id = GetCurrentThreadId (); } -bool -cygthread::is () -{ - DWORD tid = GetCurrentThreadId (); - - for (DWORD i = 0; i < NTHREADS; i++) - if (threads[i].id == tid) - return 1; - - return 0; -} - cygthread * cygthread::freerange () { diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index 9d10bb266..ff174c98c 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -30,7 +30,6 @@ class cygthread static void init (); bool detach (HANDLE = NULL); operator HANDLE (); - static bool is (); void * operator new (size_t); static cygthread *freerange (); void exit_thread (); diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 640db218e..616090dfd 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -29,6 +29,7 @@ details. */ #include "pinfo.h" #include "shared_info.h" #include "cygthread.h" +#include "cygtls.h" #define CONVERT_LIMIT 16384 @@ -250,7 +251,7 @@ fhandler_console::read (void *pv, size_t& buflen) char tmp[60]; w4[0] = h; - if (cygthread::is ()) + if (&_my_tls != _main_tls) nwait = 1; else { diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index aee32ac1b..56b068cc5 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -32,6 +32,7 @@ #include "sigproc.h" #include "cygthread.h" #include "select.h" +#include "wininfo.h" #include extern bool fdsock (cygheap_fdmanip& fd, const device *, SOCKET soc); @@ -1374,7 +1375,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) break; } case FIOASYNC: - res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, + res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, *(int *) p ? ASYNC_MASK : 0); syscall_printf ("Async I/O on socket %s", *(int *) p ? "started" : "cancelled"); @@ -1390,7 +1391,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) * blocking mode */ if (cmd == FIONBIO && *(int *) p == 0) - WSAAsyncSelect (get_socket (), gethwnd (), 0, 0); + WSAAsyncSelect (get_socket (), winmsg, 0, 0); res = ioctlsocket (get_socket (), cmd, (unsigned long *) p); if (res == SOCKET_ERROR) set_winsock_errno (); @@ -1400,7 +1401,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) *(int *) p ? "non" : ""); /* Start AsyncSelect if async socket unblocked */ if (*(int *) p && async_io ()) - WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, ASYNC_MASK); + WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK); set_nonblocking (*(int *) p); } diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index bd89793fd..a7994048d 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -22,11 +22,19 @@ details. */ #include #include "sync.h" #include "security.h" +#include "thread.h" +#include "cygtls.h" #undef WaitForSingleObject DWORD NO_COPY muto::exiting_thread; +void +muto::grab () +{ + tls = &_my_tls; +} + /* Constructor */ muto * muto::init (const char *s) @@ -69,13 +77,13 @@ muto::~muto () int muto::acquire (DWORD ms) { - DWORD this_tid = GetCurrentThreadId (); + void *this_tls = &_my_tls; #if 0 if (exiting_thread) return this_tid == exiting_thread; #endif - if (tid != this_tid) + if (tls != this_tls) { /* Increment the waiters part of the class. Need to do this first to avoid potential races. */ @@ -97,19 +105,25 @@ muto::acquire (DWORD ms) if (!ms) InterlockedIncrement (&waiters); - tid = this_tid; /* register this thread. */ + tls = this_tls; /* register this thread. */ } return ++visits; /* Increment visit count. */ } +bool +muto::acquired () +{ + return tls == &_my_tls; +} + /* Return the muto lock. Needs to be called once per every acquire. */ int muto::release () { - DWORD this_tid = GetCurrentThreadId (); + void *this_tls = &_my_tls; - if (tid != this_tid || !visits) + if (tls != this_tls || !visits) { SetLastError (ERROR_NOT_OWNER); /* Didn't have the lock. */ return 0; /* failed. */ @@ -118,33 +132,24 @@ muto::release () /* FIXME: Need to check that other thread has not exited, too. */ if (!--visits) { - tid = 0; /* We were the last unlocker. */ + tls = 0; /* We were the last unlocker. */ (void) InterlockedExchange (&sync, 0); /* Reset trigger. */ /* This thread had incremented waiters but had never decremented it. Decrement it now. If it is >= 0 then there are possibly other threads waiting for the lock, so trigger bruteforce. */ if (InterlockedDecrement (&waiters) >= 0) (void) SetEvent (bruteforce); /* Wake up one of the waiting threads */ + else if (*name == '!') + { + CloseHandle (bruteforce); /* If *name == '!' and there are no + other waiters, then this is the + last time this muto will ever be + used, so close the handle. */ +#ifdef DEBUGGING + bruteforce = NULL; +#endif + } } return 1; /* success. */ } - -bool -muto::acquired () -{ - return tid == GetCurrentThreadId (); -} - -/* Call only when we're exiting. This is not thread safe. */ -void -muto::reset () -{ - visits = sync = tid = 0; - InterlockedExchange (&waiters, -1); - if (bruteforce) - { - CloseHandle (bruteforce); - bruteforce = CreateEvent (&sec_none_nih, FALSE, FALSE, name); - } -} diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index 24de97428..7e8b60c10 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -22,7 +22,7 @@ class muto HANDLE bruteforce; /* event handle used to control waiting for lock. */ public: LONG visits; /* Count of number of times a thread has called acquire. */ - DWORD tid; /* Thread Id of lock owner. */ + void *tls; /* Tls of lock owner. */ // class muto *next; const char *name; @@ -35,12 +35,9 @@ public: int acquire (DWORD ms = INFINITE) __attribute__ ((regparm (2))); /* Acquire the lock. */ int release () __attribute__ ((regparm (1))); /* Release the lock. */ - /* Return true if caller thread owns the lock. */ - int ismine () {return tid == GetCurrentThreadId ();} - DWORD owner () {return tid;} - int unstable () {return !tid && (sync || waiters >= 0);} - void reset () __attribute__ ((regparm (1))); - bool acquired (); + bool acquired () __attribute__ ((regparm (1))); + void upforgrabs () {tls = this;} // just set to an invalid address + void grab () __attribute__ ((regparm (1))); static void set_exiting_thread () {exiting_thread = GetCurrentThreadId ();} }; @@ -59,4 +56,11 @@ extern muto muto_start; static muto __storage __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy1"))); \ __name = __storage.init (#__name); \ }) + +/* Use a statically allocated buffer as the storage for a muto */ +#define new_muto_name(__var, __name) \ +({ \ + static muto __var##_storage __attribute__((nocommon)) __attribute__((section(".data_cygwin_nocopy1"))); \ + __var = __var##_storage.init (__name); \ +}) #endif /*_SYNC_H*/ diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc index d005ae69b..a04f7c51d 100644 --- a/winsup/cygwin/window.cc +++ b/winsup/cygwin/window.cc @@ -24,14 +24,22 @@ details. */ #include "perprocess.h" #include "security.h" #include "cygthread.h" +#include "thread.h" +#include "cygtls.h" +#include "sync.h" +#include "wininfo.h" -static NO_COPY UINT timer_active = 0; -static NO_COPY struct itimerval itv; -static NO_COPY DWORD start_time; -static NO_COPY HWND ourhwnd = NULL; +wininfo NO_COPY winmsg; -static LRESULT CALLBACK -WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +muto NO_COPY *wininfo::lock; + +wininfo::wininfo () +{ + new_muto_name (lock, "!winlock"); +} + +int __stdcall +wininfo::process (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { #ifndef NOSTRACE strace.wm (uMsg, wParam, lParam); @@ -50,9 +58,7 @@ WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) itv.it_interval.tv_usec / 1000; KillTimer (hwnd, timer_active); if (!elapse) - { - timer_active = 0; - } + timer_active = 0; else { timer_active = SetTimer (hwnd, 1, elapse, NULL); @@ -73,19 +79,25 @@ WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } } -static HANDLE window_started; +static LRESULT CALLBACK +process_window_events (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return winmsg.process (hwnd, uMsg, wParam, lParam); +} -static DWORD WINAPI -Winmain (VOID *) +/* Handle windows events. Inherits ownership of the wininfo lock */ +DWORD WINAPI +wininfo::winthread () { MSG msg; WNDCLASS wc; static NO_COPY char classname[] = "CygwinWndClass"; + lock->grab (); /* Register the window class for the main window. */ wc.style = 0; - wc.lpfnWndProc = (WNDPROC) WndProc; + wc.lpfnWndProc = (WNDPROC) process_window_events; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = user_data->hmodule; @@ -96,60 +108,63 @@ Winmain (VOID *) wc.lpszClassName = classname; if (!RegisterClass (&wc)) - { - system_printf ("Cannot register window class, %E"); - return FALSE; - } + api_fatal ("cannot register window class, %E"); /* Create hidden window. */ - ourhwnd = CreateWindow (classname, classname, WS_POPUP, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - (HWND) NULL, (HMENU) NULL, user_data->hmodule, - (LPVOID) NULL); + hwnd = CreateWindow (classname, classname, WS_POPUP, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + (HWND) NULL, (HMENU) NULL, user_data->hmodule, + (LPVOID) NULL); + if (!hwnd) + api_fatal ("couldn't create window, %E"); + lock->release (); - SetEvent (window_started); - - if (!ourhwnd) - { - system_printf ("Cannot create window"); - return FALSE; - } - - /* Start the message loop. */ - - while (GetMessage (&msg, ourhwnd, 0, 0) == TRUE) + while (GetMessage (&msg, hwnd, 0, 0) == TRUE) DispatchMessage (&msg); return 0; } -HWND __stdcall -gethwnd () +static DWORD WINAPI +winthread (VOID *arg) { - if (ourhwnd != NULL) - return ourhwnd; + return ((wininfo *) arg)->winthread (); +} - cygthread *h; +wininfo::operator +HWND () +{ + if (hwnd) + return hwnd; - window_started = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); - h = new cygthread (Winmain, NULL, "win"); - h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); - WaitForSingleObject (window_started, INFINITE); - CloseHandle (window_started); - h->zap_h (); - return ourhwnd; + lock->acquire (); + if (!hwnd) + { + lock->upforgrabs (); + cygthread *h = new cygthread (::winthread, this, "win"); + h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); + h->zap_h (); + lock->acquire (); + } + lock->release (); + return hwnd; } extern "C" int setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) { - UINT elapse; - if (which != ITIMER_REAL) { set_errno (ENOSYS); return -1; } + return winmsg.setitimer (value, oldvalue); +} + +/* FIXME: Very racy */ +int __stdcall +wininfo::setitimer (const struct itimerval *value, struct itimerval *oldvalue) +{ /* Check if we will wrap */ if (itv.it_value.tv_sec >= (long) (UINT_MAX / 1000)) { @@ -158,7 +173,7 @@ setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) } if (timer_active) { - KillTimer (gethwnd (), timer_active); + KillTimer (winmsg, timer_active); timer_active = 0; } if (oldvalue) @@ -169,13 +184,13 @@ setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) return -1; } itv = *value; - elapse = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; + UINT elapse = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; if (elapse == 0) if (itv.it_value.tv_usec) elapse = 1; else return 0; - if (!(timer_active = SetTimer (gethwnd (), 1, elapse, NULL))) + if (!(timer_active = SetTimer (winmsg, 1, elapse, NULL))) { __seterrno (); return -1; @@ -187,8 +202,6 @@ setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue) extern "C" int getitimer (int which, struct itimerval *value) { - UINT elapse, val; - if (which != ITIMER_REAL) { set_errno (EINVAL); @@ -199,6 +212,13 @@ getitimer (int which, struct itimerval *value) set_errno (EFAULT); return -1; } + return winmsg.getitimer (value); +} + +/* FIXME: racy */ +int __stdcall +wininfo::getitimer (struct itimerval *value) +{ *value = itv; if (!timer_active) { @@ -206,6 +226,9 @@ getitimer (int which, struct itimerval *value) value->it_value.tv_usec = 0; return 0; } + + UINT elapse, val; + elapse = GetTickCount () - start_time; val = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000; val -= elapse; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 4c57c3776..cd698ba56 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -217,8 +217,6 @@ void events_terminate (void); void __stdcall close_all_files (); -/* Invisible window initialization/termination. */ -HWND __stdcall gethwnd (void); /* Check if running in a visible window station. */ extern bool has_visible_window_station (void);