diff options
author | marha <marha@users.sourceforge.net> | 2010-05-19 10:32:31 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-05-19 10:32:31 +0000 |
commit | b16c0295c9f95426980d567e93ae00c52545b3fa (patch) | |
tree | d25e3271be998e47e0ff07048d8297001409ea5f /libX11/src/locking.c | |
parent | c1b8f2475ebdeb148f4a27b78ed3cb24c68a92c4 (diff) | |
parent | 153f5cafa19da4e4c0cf21e9c909958359ed8ebd (diff) | |
download | vcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.tar.gz vcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.tar.bz2 vcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.zip |
svn merge "^/branches/released" .
Diffstat (limited to 'libX11/src/locking.c')
-rw-r--r-- | libX11/src/locking.c | 1243 |
1 files changed, 623 insertions, 620 deletions
diff --git a/libX11/src/locking.c b/libX11/src/locking.c index 3f93d0cd8..008a14863 100644 --- a/libX11/src/locking.c +++ b/libX11/src/locking.c @@ -1,620 +1,623 @@ -/* - -Copyright 1992, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ - -/* - * Author: Stephen Gildea, MIT X Consortium - * - * locking.c - multi-thread locking routines implemented in C Threads - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "Xlibint.h" -#undef _XLockMutex -#undef _XUnlockMutex -#undef _XCreateMutex -#undef _XFreeMutex - -#ifdef XTHREADS - -#ifdef __UNIXWARE__ -#include <dlfcn.h> -#endif - -#include "locking.h" -#ifdef XTHREADS_WARN -#include <stdio.h> /* for warn/debug stuff */ -#endif - -/* Additional arguments for source code location lock call was made from */ -#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) -# define XTHREADS_FILE_LINE_ARGS \ - , \ - char* file, /* source file, from macro */ \ - int line -#else -# define XTHREADS_FILE_LINE_ARGS /* None */ -#endif - - -#define NUM_FREE_CVLS 4 - -/* in lcWrap.c */ -extern LockInfoPtr _Xi18n_lock; - -#ifdef WIN32 -static DWORD _X_TlsIndex = (DWORD)-1; - -void _Xthread_init(void) -{ - if (_X_TlsIndex == (DWORD)-1) - _X_TlsIndex = TlsAlloc(); -} - -struct _xthread_waiter * -_Xthread_waiter(void) -{ - struct _xthread_waiter *me; - - if (!(me = TlsGetValue(_X_TlsIndex))) { - me = (struct _xthread_waiter *)xmalloc(sizeof(struct _xthread_waiter)); - me->sem = CreateSemaphore(NULL, 0, 1, NULL); - me->next = NULL; - TlsSetValue(_X_TlsIndex, me); - } - return me; -} -#endif /* WIN32 */ - -static xthread_t _Xthread_self(void) -{ - return xthread_self(); -} - -static LockInfoRec global_lock; -static LockInfoRec i18n_lock; - -static void _XLockMutex( - LockInfoPtr lip - XTHREADS_FILE_LINE_ARGS - ) -{ - xmutex_lock(lip->lock); -} - -static void _XUnlockMutex( - LockInfoPtr lip - XTHREADS_FILE_LINE_ARGS - ) -{ - xmutex_unlock(lip->lock); -} - -static void _XCreateMutex( - LockInfoPtr lip) -{ - lip->lock = xmutex_malloc(); - if (lip->lock) { - xmutex_init(lip->lock); - xmutex_set_name(lip->lock, "Xlib"); - } -} - -static void _XFreeMutex( - LockInfoPtr lip) -{ - xmutex_clear(lip->lock); - xmutex_free(lip->lock); -} - -#ifdef XTHREADS_WARN -static char *locking_file; -static int locking_line; -static xthread_t locking_thread; -static Bool xlibint_unlock = False; /* XlibInt.c may Unlock and re-Lock */ - -/* history that is useful to examine in a debugger */ -#define LOCK_HIST_SIZE 21 - -static struct { - Bool lockp; /* True for lock, False for unlock */ - xthread_t thread; - char *file; - int line; -} locking_history[LOCK_HIST_SIZE]; - -int lock_hist_loc = 0; /* next slot to fill */ - -static void _XLockDisplayWarn( - Display *dpy, - char *file, /* source file, from macro */ - int line) -{ - xthread_t self; - xthread_t old_locker; - - self = xthread_self(); - old_locker = locking_thread; - if (xthread_have_id(old_locker)) { - if (xthread_equal(old_locker, self)) - printf("Xlib ERROR: %s line %d thread %x: locking display already locked at %s line %d\n", - file, line, self, locking_file, locking_line); -#ifdef XTHREADS_DEBUG - else - printf("%s line %d: thread %x waiting on lock held by %s line %d thread %x\n", - file, line, self, - locking_file, locking_line, old_locker); -#endif /* XTHREADS_DEBUG */ - } - - xmutex_lock(dpy->lock->mutex); - - if (strcmp(file, "XlibInt.c") == 0) { - if (!xlibint_unlock) - printf("Xlib ERROR: XlibInt.c line %d thread %x locking display it did not unlock\n", - line, self); - xlibint_unlock = False; - } - -#ifdef XTHREADS_DEBUG - /* if (old_locker && old_locker != self) */ - if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ - printf("%s line %d: thread %x got display lock\n", file, line, self); -#endif /* XTHREADS_DEBUG */ - - locking_thread = self; - if (strcmp(file, "XlibInt.c") != 0) { - locking_file = file; - locking_line = line; - } - locking_history[lock_hist_loc].file = file; - locking_history[lock_hist_loc].line = line; - locking_history[lock_hist_loc].thread = self; - locking_history[lock_hist_loc].lockp = True; - lock_hist_loc++; - if (lock_hist_loc >= LOCK_HIST_SIZE) - lock_hist_loc = 0; -} -#endif /* XTHREADS_WARN */ - -static void _XUnlockDisplay( - Display *dpy - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN - xthread_t self = xthread_self(); - -#ifdef XTHREADS_DEBUG - if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ - printf("%s line %d: thread %x unlocking display\n", file, line, self); -#endif /* XTHREADS_DEBUG */ - - if (!xthread_have_id(locking_thread)) - printf("Xlib ERROR: %s line %d thread %x: unlocking display that is not locked\n", - file, line, self); - else if (strcmp(file, "XlibInt.c") == 0) - xlibint_unlock = True; -#ifdef XTHREADS_DEBUG - else if (strcmp(file, locking_file) != 0) - /* not always an error because locking_file is not per-thread */ - printf("%s line %d: unlocking display locked from %s line %d (probably okay)\n", - file, line, locking_file, locking_line); -#endif /* XTHREADS_DEBUG */ - xthread_clear_id(locking_thread); - - locking_history[lock_hist_loc].file = file; - locking_history[lock_hist_loc].line = line; - locking_history[lock_hist_loc].thread = self; - locking_history[lock_hist_loc].lockp = False; - lock_hist_loc++; - if (lock_hist_loc >= LOCK_HIST_SIZE) - lock_hist_loc = 0; -#endif /* XTHREADS_WARN */ - xmutex_unlock(dpy->lock->mutex); -} - - -static struct _XCVList *_XCreateCVL( - Display *dpy) -{ - struct _XCVList *cvl; - - if ((cvl = dpy->lock->free_cvls) != NULL) { - dpy->lock->free_cvls = cvl->next; - dpy->lock->num_free_cvls--; - } else { - cvl = (struct _XCVList *)Xmalloc(sizeof(struct _XCVList)); - if (!cvl) - return NULL; - cvl->cv = xcondition_malloc(); - if (!cvl->cv) { - Xfree(cvl); - return NULL; - } - xcondition_init(cvl->cv); - xcondition_set_name(cvl->cv, "Xlib read queue"); - } - cvl->next = NULL; - return cvl; -} - -/* Put ourselves on the queue to read the connection. - Allocates and returns a queue element. */ - -static struct _XCVList * -_XPushReader( - Display *dpy, - struct _XCVList ***tail) -{ - struct _XCVList *cvl; - - cvl = _XCreateCVL(dpy); -#ifdef XTHREADS_DEBUG - printf("_XPushReader called in thread %x, pushing %x\n", - xthread_self(), cvl); -#endif - **tail = cvl; - *tail = &cvl->next; - return cvl; -} - -/* signal the next thread waiting to read the connection */ - -static void _XPopReader( - Display *dpy, - struct _XCVList **list, - struct _XCVList ***tail) -{ - register struct _XCVList *front = *list; - -#ifdef XTHREADS_DEBUG - printf("_XPopReader called in thread %x, popping %x\n", - xthread_self(), front); -#endif - - if (dpy->flags & XlibDisplayProcConni) - /* we never added ourself in the first place */ - return; - - if (front) { /* check "front" for paranoia */ - *list = front->next; - if (*tail == &front->next) /* did we free the last elt? */ - *tail = list; - if (dpy->lock->num_free_cvls < NUM_FREE_CVLS) { - front->next = dpy->lock->free_cvls; - dpy->lock->free_cvls = front; - dpy->lock->num_free_cvls++; - } else { - xcondition_clear(front->cv); - Xfree((char *)front->cv); - Xfree((char *)front); - } - } - - /* signal new front after it is in place */ - if ((dpy->lock->reply_first = (dpy->lock->reply_awaiters != NULL))) { - ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); - } else if (dpy->lock->event_awaiters) { - ConditionSignal(dpy, dpy->lock->event_awaiters->cv); - } -} - -static void _XConditionWait( - xcondition_t cv, - xmutex_t mutex - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN - xthread_t self = xthread_self(); - char *old_file = locking_file; - int old_line = locking_line; - -#ifdef XTHREADS_DEBUG - printf("line %d thread %x in condition wait\n", line, self); -#endif - xthread_clear_id(locking_thread); - - locking_history[lock_hist_loc].file = file; - locking_history[lock_hist_loc].line = line; - locking_history[lock_hist_loc].thread = self; - locking_history[lock_hist_loc].lockp = False; - lock_hist_loc++; - if (lock_hist_loc >= LOCK_HIST_SIZE) - lock_hist_loc = 0; -#endif /* XTHREADS_WARN */ - - xcondition_wait(cv, mutex); - -#ifdef XTHREADS_WARN - locking_thread = self; - locking_file = old_file; - locking_line = old_line; - - locking_history[lock_hist_loc].file = file; - locking_history[lock_hist_loc].line = line; - locking_history[lock_hist_loc].thread = self; - locking_history[lock_hist_loc].lockp = True; - lock_hist_loc++; - if (lock_hist_loc >= LOCK_HIST_SIZE) - lock_hist_loc = 0; -#ifdef XTHREADS_DEBUG - printf("line %d thread %x was signaled\n", line, self); -#endif /* XTHREADS_DEBUG */ -#endif /* XTHREADS_WARN */ -} - -static void _XConditionSignal( - xcondition_t cv - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN -#ifdef XTHREADS_DEBUG - printf("line %d thread %x is signalling\n", line, xthread_self()); -#endif -#endif - xcondition_signal(cv); -} - - -static void _XConditionBroadcast( - xcondition_t cv - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN -#ifdef XTHREADS_DEBUG - printf("line %d thread %x is broadcasting\n", line, xthread_self()); -#endif -#endif - xcondition_broadcast(cv); -} - - -static void _XFreeDisplayLock( - Display *dpy) -{ - struct _XCVList *cvl; - - if (dpy->lock != NULL) { - if (dpy->lock->mutex != NULL) { - xmutex_clear(dpy->lock->mutex); - xmutex_free(dpy->lock->mutex); - } - if (dpy->lock->cv != NULL) { - xcondition_clear(dpy->lock->cv); - xcondition_free(dpy->lock->cv); - } - if (dpy->lock->writers != NULL) { - xcondition_clear(dpy->lock->writers); - xcondition_free(dpy->lock->writers); - } - while ((cvl = dpy->lock->free_cvls)) { - dpy->lock->free_cvls = cvl->next; - xcondition_clear(cvl->cv); - Xfree((char *)cvl->cv); - Xfree((char *)cvl); - } - Xfree((char *)dpy->lock); - dpy->lock = NULL; - } - if (dpy->lock_fns != NULL) { - Xfree((char *)dpy->lock_fns); - dpy->lock_fns = NULL; - } -} - -/* - * wait for thread with user-level display lock to release it. - */ - -static void _XDisplayLockWait( - Display *dpy) -{ - xthread_t self; - - while (dpy->lock->locking_level > 0) { - self = xthread_self(); - if (xthread_equal(dpy->lock->locking_thread, self)) - break; - ConditionWait(dpy, dpy->lock->cv); - } -} - -static void _XLockDisplay( - Display *dpy - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN - _XLockDisplayWarn(dpy, file, line); -#else - xmutex_lock(dpy->lock->mutex); -#endif - if (dpy->lock->locking_level > 0) - _XDisplayLockWait(dpy); -} - -/* - * _XReply is allowed to exit from select/poll and clean up even if a - * user-level lock is in force, so it uses this instead of _XFancyLockDisplay. - */ -static void _XInternalLockDisplay( - Display *dpy, - Bool wskip - XTHREADS_FILE_LINE_ARGS - ) -{ -#ifdef XTHREADS_WARN - _XLockDisplayWarn(dpy, file, line); -#else - xmutex_lock(dpy->lock->mutex); -#endif - if (!wskip && dpy->lock->locking_level > 0) - _XDisplayLockWait(dpy); -} - -static void _XUserLockDisplay( - register Display* dpy) -{ - if (++dpy->lock->locking_level == 1) { - dpy->lock->lock_wait = _XDisplayLockWait; - dpy->lock->locking_thread = xthread_self(); - } -} - -static -void _XUserUnlockDisplay( - register Display* dpy) -{ - if (dpy->lock->locking_level > 0 && --dpy->lock->locking_level == 0) { - /* signal other threads that might be waiting in XLockDisplay */ - ConditionBroadcast(dpy, dpy->lock->cv); - dpy->lock->lock_wait = NULL; - xthread_clear_id(dpy->lock->locking_thread); - } -} - -/* returns 0 if initialized ok, -1 if unable to allocate - a mutex or other memory */ - -static int _XInitDisplayLock( - Display *dpy) -{ - dpy->lock_fns = (struct _XLockPtrs*)Xmalloc(sizeof(struct _XLockPtrs)); - if (dpy->lock_fns == NULL) - return -1; - dpy->lock = (struct _XLockInfo *)Xmalloc(sizeof(struct _XLockInfo)); - if (dpy->lock == NULL) { - _XFreeDisplayLock(dpy); - return -1; - } - dpy->lock->cv = xcondition_malloc(); - dpy->lock->mutex = xmutex_malloc(); - dpy->lock->writers = xcondition_malloc(); - if (!dpy->lock->cv || !dpy->lock->mutex || !dpy->lock->writers) { - _XFreeDisplayLock(dpy); - return -1; - } - - dpy->lock->reply_bytes_left = 0; - dpy->lock->reply_was_read = False; - dpy->lock->reply_awaiters = NULL; - dpy->lock->reply_awaiters_tail = &dpy->lock->reply_awaiters; - dpy->lock->event_awaiters = NULL; - dpy->lock->event_awaiters_tail = &dpy->lock->event_awaiters; - dpy->lock->reply_first = False; - dpy->lock->locking_level = 0; - dpy->lock->num_free_cvls = 0; - dpy->lock->free_cvls = NULL; - xthread_clear_id(dpy->lock->locking_thread); - xthread_clear_id(dpy->lock->reading_thread); - xthread_clear_id(dpy->lock->conni_thread); - xmutex_init(dpy->lock->mutex); - xmutex_set_name(dpy->lock->mutex, "Xlib Display"); - xcondition_init(dpy->lock->cv); - xcondition_set_name(dpy->lock->cv, "XLockDisplay"); - xcondition_init(dpy->lock->writers); - xcondition_set_name(dpy->lock->writers, "Xlib wait for writable"); - dpy->lock_fns->lock_display = _XLockDisplay; - dpy->lock->internal_lock_display = _XInternalLockDisplay; - dpy->lock_fns->unlock_display = _XUnlockDisplay; - dpy->lock->user_lock_display = _XUserLockDisplay; - dpy->lock->user_unlock_display = _XUserUnlockDisplay; - dpy->lock->pop_reader = _XPopReader; - dpy->lock->push_reader = _XPushReader; - dpy->lock->condition_wait = _XConditionWait; - dpy->lock->condition_signal = _XConditionSignal; - dpy->lock->condition_broadcast = _XConditionBroadcast; - dpy->lock->create_cvl = _XCreateCVL; - dpy->lock->lock_wait = NULL; /* filled in by XLockDisplay() */ - - return 0; -} - -#ifdef __UNIXWARE__ -xthread_t __x11_thr_self() { return 0; } -xthread_t (*_x11_thr_self)() = __x11_thr_self; -#endif - - -Status XInitThreads(void) -{ - if (_Xglobal_lock) - return 1; -#ifdef __UNIXWARE__ - else { - void *dl_handle = dlopen(NULL, RTLD_LAZY); - if (!dl_handle || - ((_x11_thr_self = (xthread_t(*)())dlsym(dl_handle,"thr_self")) == 0)) { - _x11_thr_self = __x11_thr_self; - (void) fprintf (stderr, - "XInitThreads called, but no libthread in the calling program!\n" ); - } - } -#endif /* __UNIXWARE__ */ -#ifdef xthread_init - xthread_init(); /* return value? */ -#endif - if (!(global_lock.lock = xmutex_malloc())) - return 0; - if (!(i18n_lock.lock = xmutex_malloc())) { - xmutex_free(global_lock.lock); - global_lock.lock = NULL; - return 0; - } - _Xglobal_lock = &global_lock; - xmutex_init(_Xglobal_lock->lock); - xmutex_set_name(_Xglobal_lock->lock, "Xlib global"); - _Xi18n_lock = &i18n_lock; - xmutex_init(_Xi18n_lock->lock); - xmutex_set_name(_Xi18n_lock->lock, "Xlib i18n"); - _XLockMutex_fn = _XLockMutex; - _XUnlockMutex_fn = _XUnlockMutex; - _XCreateMutex_fn = _XCreateMutex; - _XFreeMutex_fn = _XFreeMutex; - _XInitDisplayLock_fn = _XInitDisplayLock; - _XFreeDisplayLock_fn = _XFreeDisplayLock; - _Xthread_self_fn = _Xthread_self; - -#ifdef XTHREADS_WARN -#ifdef XTHREADS_DEBUG - setlinebuf(stdout); /* for debugging messages */ -#endif -#endif - - return 1; -} - -#else /* XTHREADS */ -Status XInitThreads(void) -{ - return 0; -} -#endif /* XTHREADS */ +/*
+
+Copyright 1992, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+/*
+ * Author: Stephen Gildea, MIT X Consortium
+ *
+ * locking.c - multi-thread locking routines implemented in C Threads
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "Xlibint.h"
+#undef _XLockMutex
+#undef _XUnlockMutex
+#undef _XCreateMutex
+#undef _XFreeMutex
+
+#ifdef XTHREADS
+
+#ifdef __UNIXWARE__
+#include <dlfcn.h>
+#endif
+
+#include "Xprivate.h"
+#include "locking.h"
+#ifdef XTHREADS_WARN
+#include <stdio.h> /* for warn/debug stuff */
+#endif
+
+/* Additional arguments for source code location lock call was made from */
+#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
+# define XTHREADS_FILE_LINE_ARGS \
+ , \
+ char* file, /* source file, from macro */ \
+ int line
+#else
+# define XTHREADS_FILE_LINE_ARGS /* None */
+#endif
+
+
+#define NUM_FREE_CVLS 4
+
+/* in lcWrap.c */
+extern LockInfoPtr _Xi18n_lock;
+
+#ifdef WIN32
+static DWORD _X_TlsIndex = (DWORD)-1;
+
+void _Xthread_init(void)
+{
+ if (_X_TlsIndex == (DWORD)-1)
+ _X_TlsIndex = TlsAlloc();
+}
+
+struct _xthread_waiter *
+_Xthread_waiter(void)
+{
+ struct _xthread_waiter *me;
+
+ if (!(me = TlsGetValue(_X_TlsIndex))) {
+ me = (struct _xthread_waiter *)xmalloc(sizeof(struct _xthread_waiter));
+ me->sem = CreateSemaphore(NULL, 0, 1, NULL);
+ me->next = NULL;
+ TlsSetValue(_X_TlsIndex, me);
+ }
+ return me;
+}
+#endif /* WIN32 */
+
+static xthread_t _Xthread_self(void)
+{
+ return xthread_self();
+}
+
+static LockInfoRec global_lock;
+static LockInfoRec i18n_lock;
+
+static void _XLockMutex(
+ LockInfoPtr lip
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+ xmutex_lock(lip->lock);
+}
+
+static void _XUnlockMutex(
+ LockInfoPtr lip
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+ xmutex_unlock(lip->lock);
+}
+
+static void _XCreateMutex(
+ LockInfoPtr lip)
+{
+ lip->lock = xmutex_malloc();
+ if (lip->lock) {
+ xmutex_init(lip->lock);
+ xmutex_set_name(lip->lock, "Xlib");
+ }
+}
+
+static void _XFreeMutex(
+ LockInfoPtr lip)
+{
+ xmutex_clear(lip->lock);
+ xmutex_free(lip->lock);
+}
+
+#ifdef XTHREADS_WARN
+static char *locking_file;
+static int locking_line;
+static xthread_t locking_thread;
+static Bool xlibint_unlock = False; /* XlibInt.c may Unlock and re-Lock */
+
+/* history that is useful to examine in a debugger */
+#define LOCK_HIST_SIZE 21
+
+static struct {
+ Bool lockp; /* True for lock, False for unlock */
+ xthread_t thread;
+ char *file;
+ int line;
+} locking_history[LOCK_HIST_SIZE];
+
+int lock_hist_loc = 0; /* next slot to fill */
+
+static void _XLockDisplayWarn(
+ Display *dpy,
+ char *file, /* source file, from macro */
+ int line)
+{
+ xthread_t self;
+ xthread_t old_locker;
+
+ self = xthread_self();
+ old_locker = locking_thread;
+ if (xthread_have_id(old_locker)) {
+ if (xthread_equal(old_locker, self))
+ printf("Xlib ERROR: %s line %d thread %x: locking display already locked at %s line %d\n",
+ file, line, self, locking_file, locking_line);
+#ifdef XTHREADS_DEBUG
+ else
+ printf("%s line %d: thread %x waiting on lock held by %s line %d thread %x\n",
+ file, line, self,
+ locking_file, locking_line, old_locker);
+#endif /* XTHREADS_DEBUG */
+ }
+
+ xmutex_lock(dpy->lock->mutex);
+
+ if (strcmp(file, "XlibInt.c") == 0) {
+ if (!xlibint_unlock)
+ printf("Xlib ERROR: XlibInt.c line %d thread %x locking display it did not unlock\n",
+ line, self);
+ xlibint_unlock = False;
+ }
+
+#ifdef XTHREADS_DEBUG
+ /* if (old_locker && old_locker != self) */
+ if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */
+ printf("%s line %d: thread %x got display lock\n", file, line, self);
+#endif /* XTHREADS_DEBUG */
+
+ locking_thread = self;
+ if (strcmp(file, "XlibInt.c") != 0) {
+ locking_file = file;
+ locking_line = line;
+ }
+ locking_history[lock_hist_loc].file = file;
+ locking_history[lock_hist_loc].line = line;
+ locking_history[lock_hist_loc].thread = self;
+ locking_history[lock_hist_loc].lockp = True;
+ lock_hist_loc++;
+ if (lock_hist_loc >= LOCK_HIST_SIZE)
+ lock_hist_loc = 0;
+}
+#endif /* XTHREADS_WARN */
+
+static void _XUnlockDisplay(
+ Display *dpy
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+ xthread_t self = xthread_self();
+
+#ifdef XTHREADS_DEBUG
+ if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */
+ printf("%s line %d: thread %x unlocking display\n", file, line, self);
+#endif /* XTHREADS_DEBUG */
+
+ if (!xthread_have_id(locking_thread))
+ printf("Xlib ERROR: %s line %d thread %x: unlocking display that is not locked\n",
+ file, line, self);
+ else if (strcmp(file, "XlibInt.c") == 0)
+ xlibint_unlock = True;
+#ifdef XTHREADS_DEBUG
+ else if (strcmp(file, locking_file) != 0)
+ /* not always an error because locking_file is not per-thread */
+ printf("%s line %d: unlocking display locked from %s line %d (probably okay)\n",
+ file, line, locking_file, locking_line);
+#endif /* XTHREADS_DEBUG */
+ xthread_clear_id(locking_thread);
+
+ locking_history[lock_hist_loc].file = file;
+ locking_history[lock_hist_loc].line = line;
+ locking_history[lock_hist_loc].thread = self;
+ locking_history[lock_hist_loc].lockp = False;
+ lock_hist_loc++;
+ if (lock_hist_loc >= LOCK_HIST_SIZE)
+ lock_hist_loc = 0;
+#endif /* XTHREADS_WARN */
+ xmutex_unlock(dpy->lock->mutex);
+}
+
+
+static struct _XCVList *_XCreateCVL(
+ Display *dpy)
+{
+ struct _XCVList *cvl;
+
+ if ((cvl = dpy->lock->free_cvls) != NULL) {
+ dpy->lock->free_cvls = cvl->next;
+ dpy->lock->num_free_cvls--;
+ } else {
+ cvl = (struct _XCVList *)Xmalloc(sizeof(struct _XCVList));
+ if (!cvl)
+ return NULL;
+ cvl->cv = xcondition_malloc();
+ if (!cvl->cv) {
+ Xfree(cvl);
+ return NULL;
+ }
+ xcondition_init(cvl->cv);
+ xcondition_set_name(cvl->cv, "Xlib read queue");
+ }
+ cvl->next = NULL;
+ return cvl;
+}
+
+/* Put ourselves on the queue to read the connection.
+ Allocates and returns a queue element. */
+
+static struct _XCVList *
+_XPushReader(
+ Display *dpy,
+ struct _XCVList ***tail)
+{
+ struct _XCVList *cvl;
+
+ cvl = _XCreateCVL(dpy);
+#ifdef XTHREADS_DEBUG
+ printf("_XPushReader called in thread %x, pushing %x\n",
+ xthread_self(), cvl);
+#endif
+ **tail = cvl;
+ *tail = &cvl->next;
+ return cvl;
+}
+
+/* signal the next thread waiting to read the connection */
+
+static void _XPopReader(
+ Display *dpy,
+ struct _XCVList **list,
+ struct _XCVList ***tail)
+{
+ register struct _XCVList *front = *list;
+
+#ifdef XTHREADS_DEBUG
+ printf("_XPopReader called in thread %x, popping %x\n",
+ xthread_self(), front);
+#endif
+
+ if (dpy->flags & XlibDisplayProcConni)
+ /* we never added ourself in the first place */
+ return;
+
+ if (front) { /* check "front" for paranoia */
+ *list = front->next;
+ if (*tail == &front->next) /* did we free the last elt? */
+ *tail = list;
+ if (dpy->lock->num_free_cvls < NUM_FREE_CVLS) {
+ front->next = dpy->lock->free_cvls;
+ dpy->lock->free_cvls = front;
+ dpy->lock->num_free_cvls++;
+ } else {
+ xcondition_clear(front->cv);
+ Xfree((char *)front->cv);
+ Xfree((char *)front);
+ }
+ }
+
+ /* signal new front after it is in place */
+ if ((dpy->lock->reply_first = (dpy->lock->reply_awaiters != NULL))) {
+ ConditionSignal(dpy, dpy->lock->reply_awaiters->cv);
+ } else if (dpy->lock->event_awaiters) {
+ ConditionSignal(dpy, dpy->lock->event_awaiters->cv);
+ }
+}
+
+static void _XConditionWait(
+ xcondition_t cv,
+ xmutex_t mutex
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+ xthread_t self = xthread_self();
+ char *old_file = locking_file;
+ int old_line = locking_line;
+
+#ifdef XTHREADS_DEBUG
+ printf("line %d thread %x in condition wait\n", line, self);
+#endif
+ xthread_clear_id(locking_thread);
+
+ locking_history[lock_hist_loc].file = file;
+ locking_history[lock_hist_loc].line = line;
+ locking_history[lock_hist_loc].thread = self;
+ locking_history[lock_hist_loc].lockp = False;
+ lock_hist_loc++;
+ if (lock_hist_loc >= LOCK_HIST_SIZE)
+ lock_hist_loc = 0;
+#endif /* XTHREADS_WARN */
+
+ xcondition_wait(cv, mutex);
+
+#ifdef XTHREADS_WARN
+ locking_thread = self;
+ locking_file = old_file;
+ locking_line = old_line;
+
+ locking_history[lock_hist_loc].file = file;
+ locking_history[lock_hist_loc].line = line;
+ locking_history[lock_hist_loc].thread = self;
+ locking_history[lock_hist_loc].lockp = True;
+ lock_hist_loc++;
+ if (lock_hist_loc >= LOCK_HIST_SIZE)
+ lock_hist_loc = 0;
+#ifdef XTHREADS_DEBUG
+ printf("line %d thread %x was signaled\n", line, self);
+#endif /* XTHREADS_DEBUG */
+#endif /* XTHREADS_WARN */
+}
+
+static void _XConditionSignal(
+ xcondition_t cv
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+#ifdef XTHREADS_DEBUG
+ printf("line %d thread %x is signalling\n", line, xthread_self());
+#endif
+#endif
+ xcondition_signal(cv);
+}
+
+
+static void _XConditionBroadcast(
+ xcondition_t cv
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+#ifdef XTHREADS_DEBUG
+ printf("line %d thread %x is broadcasting\n", line, xthread_self());
+#endif
+#endif
+ xcondition_broadcast(cv);
+}
+
+
+static void _XFreeDisplayLock(
+ Display *dpy)
+{
+ struct _XCVList *cvl;
+
+ if (dpy->lock != NULL) {
+ if (dpy->lock->mutex != NULL) {
+ xmutex_clear(dpy->lock->mutex);
+ xmutex_free(dpy->lock->mutex);
+ }
+ if (dpy->lock->cv != NULL) {
+ xcondition_clear(dpy->lock->cv);
+ xcondition_free(dpy->lock->cv);
+ }
+ if (dpy->lock->writers != NULL) {
+ xcondition_clear(dpy->lock->writers);
+ xcondition_free(dpy->lock->writers);
+ }
+ while ((cvl = dpy->lock->free_cvls)) {
+ dpy->lock->free_cvls = cvl->next;
+ xcondition_clear(cvl->cv);
+ Xfree((char *)cvl->cv);
+ Xfree((char *)cvl);
+ }
+ Xfree((char *)dpy->lock);
+ dpy->lock = NULL;
+ }
+ if (dpy->lock_fns != NULL) {
+ Xfree((char *)dpy->lock_fns);
+ dpy->lock_fns = NULL;
+ }
+}
+
+/*
+ * wait for thread with user-level display lock to release it.
+ */
+
+static void _XDisplayLockWait(
+ Display *dpy)
+{
+ xthread_t self;
+
+ while (dpy->lock->locking_level > 0) {
+ self = xthread_self();
+ if (xthread_equal(dpy->lock->locking_thread, self))
+ break;
+ ConditionWait(dpy, dpy->lock->cv);
+ }
+}
+
+static void _XLockDisplay(
+ Display *dpy
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+ _XLockDisplayWarn(dpy, file, line);
+#else
+ xmutex_lock(dpy->lock->mutex);
+#endif
+ if (dpy->lock->locking_level > 0)
+ _XDisplayLockWait(dpy);
+ _XIDHandler(dpy);
+ _XSeqSyncFunction(dpy);
+}
+
+/*
+ * _XReply is allowed to exit from select/poll and clean up even if a
+ * user-level lock is in force, so it uses this instead of _XFancyLockDisplay.
+ */
+static void _XInternalLockDisplay(
+ Display *dpy,
+ Bool wskip
+ XTHREADS_FILE_LINE_ARGS
+ )
+{
+#ifdef XTHREADS_WARN
+ _XLockDisplayWarn(dpy, file, line);
+#else
+ xmutex_lock(dpy->lock->mutex);
+#endif
+ if (!wskip && dpy->lock->locking_level > 0)
+ _XDisplayLockWait(dpy);
+}
+
+static void _XUserLockDisplay(
+ register Display* dpy)
+{
+ if (++dpy->lock->locking_level == 1) {
+ dpy->lock->lock_wait = _XDisplayLockWait;
+ dpy->lock->locking_thread = xthread_self();
+ }
+}
+
+static
+void _XUserUnlockDisplay(
+ register Display* dpy)
+{
+ if (dpy->lock->locking_level > 0 && --dpy->lock->locking_level == 0) {
+ /* signal other threads that might be waiting in XLockDisplay */
+ ConditionBroadcast(dpy, dpy->lock->cv);
+ dpy->lock->lock_wait = NULL;
+ xthread_clear_id(dpy->lock->locking_thread);
+ }
+}
+
+/* returns 0 if initialized ok, -1 if unable to allocate
+ a mutex or other memory */
+
+static int _XInitDisplayLock(
+ Display *dpy)
+{
+ dpy->lock_fns = (struct _XLockPtrs*)Xmalloc(sizeof(struct _XLockPtrs));
+ if (dpy->lock_fns == NULL)
+ return -1;
+ dpy->lock = (struct _XLockInfo *)Xmalloc(sizeof(struct _XLockInfo));
+ if (dpy->lock == NULL) {
+ _XFreeDisplayLock(dpy);
+ return -1;
+ }
+ dpy->lock->cv = xcondition_malloc();
+ dpy->lock->mutex = xmutex_malloc();
+ dpy->lock->writers = xcondition_malloc();
+ if (!dpy->lock->cv || !dpy->lock->mutex || !dpy->lock->writers) {
+ _XFreeDisplayLock(dpy);
+ return -1;
+ }
+
+ dpy->lock->reply_bytes_left = 0;
+ dpy->lock->reply_was_read = False;
+ dpy->lock->reply_awaiters = NULL;
+ dpy->lock->reply_awaiters_tail = &dpy->lock->reply_awaiters;
+ dpy->lock->event_awaiters = NULL;
+ dpy->lock->event_awaiters_tail = &dpy->lock->event_awaiters;
+ dpy->lock->reply_first = False;
+ dpy->lock->locking_level = 0;
+ dpy->lock->num_free_cvls = 0;
+ dpy->lock->free_cvls = NULL;
+ xthread_clear_id(dpy->lock->locking_thread);
+ xthread_clear_id(dpy->lock->reading_thread);
+ xthread_clear_id(dpy->lock->conni_thread);
+ xmutex_init(dpy->lock->mutex);
+ xmutex_set_name(dpy->lock->mutex, "Xlib Display");
+ xcondition_init(dpy->lock->cv);
+ xcondition_set_name(dpy->lock->cv, "XLockDisplay");
+ xcondition_init(dpy->lock->writers);
+ xcondition_set_name(dpy->lock->writers, "Xlib wait for writable");
+ dpy->lock_fns->lock_display = _XLockDisplay;
+ dpy->lock->internal_lock_display = _XInternalLockDisplay;
+ dpy->lock_fns->unlock_display = _XUnlockDisplay;
+ dpy->lock->user_lock_display = _XUserLockDisplay;
+ dpy->lock->user_unlock_display = _XUserUnlockDisplay;
+ dpy->lock->pop_reader = _XPopReader;
+ dpy->lock->push_reader = _XPushReader;
+ dpy->lock->condition_wait = _XConditionWait;
+ dpy->lock->condition_signal = _XConditionSignal;
+ dpy->lock->condition_broadcast = _XConditionBroadcast;
+ dpy->lock->create_cvl = _XCreateCVL;
+ dpy->lock->lock_wait = NULL; /* filled in by XLockDisplay() */
+
+ return 0;
+}
+
+#ifdef __UNIXWARE__
+xthread_t __x11_thr_self() { return 0; }
+xthread_t (*_x11_thr_self)() = __x11_thr_self;
+#endif
+
+
+Status XInitThreads(void)
+{
+ if (_Xglobal_lock)
+ return 1;
+#ifdef __UNIXWARE__
+ else {
+ void *dl_handle = dlopen(NULL, RTLD_LAZY);
+ if (!dl_handle ||
+ ((_x11_thr_self = (xthread_t(*)())dlsym(dl_handle,"thr_self")) == 0)) {
+ _x11_thr_self = __x11_thr_self;
+ (void) fprintf (stderr,
+ "XInitThreads called, but no libthread in the calling program!\n" );
+ }
+ }
+#endif /* __UNIXWARE__ */
+#ifdef xthread_init
+ xthread_init(); /* return value? */
+#endif
+ if (!(global_lock.lock = xmutex_malloc()))
+ return 0;
+ if (!(i18n_lock.lock = xmutex_malloc())) {
+ xmutex_free(global_lock.lock);
+ global_lock.lock = NULL;
+ return 0;
+ }
+ _Xglobal_lock = &global_lock;
+ xmutex_init(_Xglobal_lock->lock);
+ xmutex_set_name(_Xglobal_lock->lock, "Xlib global");
+ _Xi18n_lock = &i18n_lock;
+ xmutex_init(_Xi18n_lock->lock);
+ xmutex_set_name(_Xi18n_lock->lock, "Xlib i18n");
+ _XLockMutex_fn = _XLockMutex;
+ _XUnlockMutex_fn = _XUnlockMutex;
+ _XCreateMutex_fn = _XCreateMutex;
+ _XFreeMutex_fn = _XFreeMutex;
+ _XInitDisplayLock_fn = _XInitDisplayLock;
+ _XFreeDisplayLock_fn = _XFreeDisplayLock;
+ _Xthread_self_fn = _Xthread_self;
+
+#ifdef XTHREADS_WARN
+#ifdef XTHREADS_DEBUG
+ setlinebuf(stdout); /* for debugging messages */
+#endif
+#endif
+
+ return 1;
+}
+
+#else /* XTHREADS */
+Status XInitThreads(void)
+{
+ return 0;
+}
+#endif /* XTHREADS */
|