11ab64890Smrg/* 261b2299dSmrg 31ab64890SmrgCopyright 1992, 1998 The Open Group 41ab64890Smrg 51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 71ab64890Smrgthe above copyright notice appear in all copies and that both that 81ab64890Smrgcopyright notice and this permission notice appear in supporting 91ab64890Smrgdocumentation. 101ab64890Smrg 111ab64890SmrgThe above copyright notice and this permission notice shall be included in 121ab64890Smrgall copies or substantial portions of the Software. 131ab64890Smrg 141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 151ab64890SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 161ab64890SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 171ab64890SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 181ab64890SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 191ab64890SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 201ab64890Smrg 211ab64890SmrgExcept as contained in this notice, the name of The Open Group shall not be 221ab64890Smrgused in advertising or otherwise to promote the sale, use or other dealings 231ab64890Smrgin this Software without prior written authorization from The Open Group. 241ab64890Smrg 251ab64890Smrg*/ 261ab64890Smrg 271ab64890Smrg/* 281ab64890Smrg * Author: Stephen Gildea, MIT X Consortium 291ab64890Smrg * 301ab64890Smrg * locking.c - multi-thread locking routines implemented in C Threads 311ab64890Smrg */ 321ab64890Smrg 331ab64890Smrg#ifdef HAVE_CONFIG_H 341ab64890Smrg#include <config.h> 351ab64890Smrg#endif 361ab64890Smrg#include "Xlibint.h" 371ab64890Smrg#undef _XLockMutex 381ab64890Smrg#undef _XUnlockMutex 391ab64890Smrg#undef _XCreateMutex 401ab64890Smrg#undef _XFreeMutex 411ab64890Smrg 421ab64890Smrg#ifdef XTHREADS 431ab64890Smrg 441ab64890Smrg#ifdef __UNIXWARE__ 451ab64890Smrg#include <dlfcn.h> 461ab64890Smrg#endif 471ab64890Smrg 4888de56ccSmrg#include "Xprivate.h" 491ab64890Smrg#include "locking.h" 501ab64890Smrg#ifdef XTHREADS_WARN 511ab64890Smrg#include <stdio.h> /* for warn/debug stuff */ 521ab64890Smrg#endif 531ab64890Smrg 542e9c7c8cSmrg/* Additional arguments for source code location lock call was made from */ 552e9c7c8cSmrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) 562e9c7c8cSmrg# define XTHREADS_FILE_LINE_ARGS \ 572e9c7c8cSmrg , \ 582e9c7c8cSmrg char* file, /* source file, from macro */ \ 592e9c7c8cSmrg int line 602e9c7c8cSmrg#else 612e9c7c8cSmrg# define XTHREADS_FILE_LINE_ARGS /* None */ 622e9c7c8cSmrg#endif 632e9c7c8cSmrg 642e9c7c8cSmrg 651ab64890Smrg#define NUM_FREE_CVLS 4 661ab64890Smrg 671ab64890Smrg/* in lcWrap.c */ 681ab64890Smrgextern LockInfoPtr _Xi18n_lock; 69d4a3aaf4Smrg/* in lcConv.c */ 70d4a3aaf4Smrgextern LockInfoPtr _conv_lock; 711ab64890Smrg 721ab64890Smrg#ifdef WIN32 731ab64890Smrgstatic DWORD _X_TlsIndex = (DWORD)-1; 741ab64890Smrg 752e9c7c8cSmrgvoid _Xthread_init(void) 761ab64890Smrg{ 771ab64890Smrg if (_X_TlsIndex == (DWORD)-1) 781ab64890Smrg _X_TlsIndex = TlsAlloc(); 791ab64890Smrg} 801ab64890Smrg 811ab64890Smrgstruct _xthread_waiter * 822e9c7c8cSmrg_Xthread_waiter(void) 831ab64890Smrg{ 841ab64890Smrg struct _xthread_waiter *me; 851ab64890Smrg 861ab64890Smrg if (!(me = TlsGetValue(_X_TlsIndex))) { 87eb411b4bSmrg me = xmalloc(sizeof(struct _xthread_waiter)); 881ab64890Smrg me->sem = CreateSemaphore(NULL, 0, 1, NULL); 891ab64890Smrg me->next = NULL; 901ab64890Smrg TlsSetValue(_X_TlsIndex, me); 911ab64890Smrg } 921ab64890Smrg return me; 931ab64890Smrg} 941ab64890Smrg#endif /* WIN32 */ 951ab64890Smrg 961ab64890Smrgstatic xthread_t _Xthread_self(void) 971ab64890Smrg{ 981ab64890Smrg return xthread_self(); 991ab64890Smrg} 1001ab64890Smrg 1011ab64890Smrgstatic LockInfoRec global_lock; 1021ab64890Smrgstatic LockInfoRec i18n_lock; 103d4a3aaf4Smrgstatic LockInfoRec conv_lock; 1041ab64890Smrg 1051ab64890Smrgstatic void _XLockMutex( 1062e9c7c8cSmrg LockInfoPtr lip 1072e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 1082e9c7c8cSmrg ) 1091ab64890Smrg{ 1101ab64890Smrg xmutex_lock(lip->lock); 1111ab64890Smrg} 1121ab64890Smrg 1131ab64890Smrgstatic void _XUnlockMutex( 1142e9c7c8cSmrg LockInfoPtr lip 1152e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 1162e9c7c8cSmrg ) 1171ab64890Smrg{ 1181ab64890Smrg xmutex_unlock(lip->lock); 1191ab64890Smrg} 1201ab64890Smrg 1211ab64890Smrgstatic void _XCreateMutex( 1221ab64890Smrg LockInfoPtr lip) 1231ab64890Smrg{ 1241ab64890Smrg lip->lock = xmutex_malloc(); 1251ab64890Smrg if (lip->lock) { 1261ab64890Smrg xmutex_init(lip->lock); 1271ab64890Smrg xmutex_set_name(lip->lock, "Xlib"); 1281ab64890Smrg } 1291ab64890Smrg} 1301ab64890Smrg 1311ab64890Smrgstatic void _XFreeMutex( 1321ab64890Smrg LockInfoPtr lip) 1331ab64890Smrg{ 1341ab64890Smrg xmutex_clear(lip->lock); 1351ab64890Smrg xmutex_free(lip->lock); 136d4a3aaf4Smrg lip->lock = NULL; 1371ab64890Smrg} 1381ab64890Smrg 1391ab64890Smrg#ifdef XTHREADS_WARN 1401ab64890Smrgstatic char *locking_file; 1411ab64890Smrgstatic int locking_line; 1421ab64890Smrgstatic xthread_t locking_thread; 1431ab64890Smrgstatic Bool xlibint_unlock = False; /* XlibInt.c may Unlock and re-Lock */ 1441ab64890Smrg 1451ab64890Smrg/* history that is useful to examine in a debugger */ 1461ab64890Smrg#define LOCK_HIST_SIZE 21 1471ab64890Smrg 1481ab64890Smrgstatic struct { 1491ab64890Smrg Bool lockp; /* True for lock, False for unlock */ 1501ab64890Smrg xthread_t thread; 1511ab64890Smrg char *file; 1521ab64890Smrg int line; 1531ab64890Smrg} locking_history[LOCK_HIST_SIZE]; 1541ab64890Smrg 1551ab64890Smrgint lock_hist_loc = 0; /* next slot to fill */ 1561ab64890Smrg 1571ab64890Smrgstatic void _XLockDisplayWarn( 1581ab64890Smrg Display *dpy, 1591ab64890Smrg char *file, /* source file, from macro */ 1601ab64890Smrg int line) 1611ab64890Smrg{ 1621ab64890Smrg xthread_t self; 1631ab64890Smrg xthread_t old_locker; 1641ab64890Smrg 1651ab64890Smrg self = xthread_self(); 1661ab64890Smrg old_locker = locking_thread; 1671ab64890Smrg if (xthread_have_id(old_locker)) { 1681ab64890Smrg if (xthread_equal(old_locker, self)) 1691ab64890Smrg printf("Xlib ERROR: %s line %d thread %x: locking display already locked at %s line %d\n", 1701ab64890Smrg file, line, self, locking_file, locking_line); 1711ab64890Smrg#ifdef XTHREADS_DEBUG 1721ab64890Smrg else 1731ab64890Smrg printf("%s line %d: thread %x waiting on lock held by %s line %d thread %x\n", 1741ab64890Smrg file, line, self, 1751ab64890Smrg locking_file, locking_line, old_locker); 1761ab64890Smrg#endif /* XTHREADS_DEBUG */ 1771ab64890Smrg } 1781ab64890Smrg 1791ab64890Smrg xmutex_lock(dpy->lock->mutex); 1801ab64890Smrg 1811ab64890Smrg if (strcmp(file, "XlibInt.c") == 0) { 1821ab64890Smrg if (!xlibint_unlock) 1831ab64890Smrg printf("Xlib ERROR: XlibInt.c line %d thread %x locking display it did not unlock\n", 1841ab64890Smrg line, self); 1851ab64890Smrg xlibint_unlock = False; 1861ab64890Smrg } 1871ab64890Smrg 1881ab64890Smrg#ifdef XTHREADS_DEBUG 1891ab64890Smrg /* if (old_locker && old_locker != self) */ 1901ab64890Smrg if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ 1911ab64890Smrg printf("%s line %d: thread %x got display lock\n", file, line, self); 1921ab64890Smrg#endif /* XTHREADS_DEBUG */ 1931ab64890Smrg 1941ab64890Smrg locking_thread = self; 1951ab64890Smrg if (strcmp(file, "XlibInt.c") != 0) { 1961ab64890Smrg locking_file = file; 1971ab64890Smrg locking_line = line; 1981ab64890Smrg } 1991ab64890Smrg locking_history[lock_hist_loc].file = file; 2001ab64890Smrg locking_history[lock_hist_loc].line = line; 2011ab64890Smrg locking_history[lock_hist_loc].thread = self; 2021ab64890Smrg locking_history[lock_hist_loc].lockp = True; 2031ab64890Smrg lock_hist_loc++; 2041ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 2051ab64890Smrg lock_hist_loc = 0; 2061ab64890Smrg} 2071ab64890Smrg#endif /* XTHREADS_WARN */ 2081ab64890Smrg 2091ab64890Smrgstatic void _XUnlockDisplay( 2102e9c7c8cSmrg Display *dpy 2112e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 2122e9c7c8cSmrg ) 2131ab64890Smrg{ 2141ab64890Smrg#ifdef XTHREADS_WARN 2151ab64890Smrg xthread_t self = xthread_self(); 2161ab64890Smrg 2171ab64890Smrg#ifdef XTHREADS_DEBUG 2181ab64890Smrg if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ 2191ab64890Smrg printf("%s line %d: thread %x unlocking display\n", file, line, self); 2201ab64890Smrg#endif /* XTHREADS_DEBUG */ 2211ab64890Smrg 2221ab64890Smrg if (!xthread_have_id(locking_thread)) 2231ab64890Smrg printf("Xlib ERROR: %s line %d thread %x: unlocking display that is not locked\n", 2241ab64890Smrg file, line, self); 2251ab64890Smrg else if (strcmp(file, "XlibInt.c") == 0) 2261ab64890Smrg xlibint_unlock = True; 2271ab64890Smrg#ifdef XTHREADS_DEBUG 2281ab64890Smrg else if (strcmp(file, locking_file) != 0) 2291ab64890Smrg /* not always an error because locking_file is not per-thread */ 2301ab64890Smrg printf("%s line %d: unlocking display locked from %s line %d (probably okay)\n", 2311ab64890Smrg file, line, locking_file, locking_line); 2321ab64890Smrg#endif /* XTHREADS_DEBUG */ 2331ab64890Smrg xthread_clear_id(locking_thread); 2341ab64890Smrg 2351ab64890Smrg locking_history[lock_hist_loc].file = file; 2361ab64890Smrg locking_history[lock_hist_loc].line = line; 2371ab64890Smrg locking_history[lock_hist_loc].thread = self; 2381ab64890Smrg locking_history[lock_hist_loc].lockp = False; 2391ab64890Smrg lock_hist_loc++; 2401ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 2411ab64890Smrg lock_hist_loc = 0; 2421ab64890Smrg#endif /* XTHREADS_WARN */ 243876003caSmrg 244876003caSmrg if (dpy->in_ifevent == 0 || !xthread_equal(dpy->ifevent_thread, xthread_self())) 245876003caSmrg xmutex_unlock(dpy->lock->mutex); 2461ab64890Smrg} 2471ab64890Smrg 2481ab64890Smrg 2491ab64890Smrgstatic struct _XCVList *_XCreateCVL( 2501ab64890Smrg Display *dpy) 2511ab64890Smrg{ 2521ab64890Smrg struct _XCVList *cvl; 2531ab64890Smrg 2541ab64890Smrg if ((cvl = dpy->lock->free_cvls) != NULL) { 2551ab64890Smrg dpy->lock->free_cvls = cvl->next; 2561ab64890Smrg dpy->lock->num_free_cvls--; 2571ab64890Smrg } else { 258eb411b4bSmrg cvl = Xmalloc(sizeof(struct _XCVList)); 2591ab64890Smrg if (!cvl) 2601ab64890Smrg return NULL; 2611ab64890Smrg cvl->cv = xcondition_malloc(); 2621ab64890Smrg if (!cvl->cv) { 2631ab64890Smrg Xfree(cvl); 2641ab64890Smrg return NULL; 2651ab64890Smrg } 2661ab64890Smrg xcondition_init(cvl->cv); 2671ab64890Smrg xcondition_set_name(cvl->cv, "Xlib read queue"); 2681ab64890Smrg } 2691ab64890Smrg cvl->next = NULL; 2701ab64890Smrg return cvl; 2711ab64890Smrg} 2721ab64890Smrg 2731ab64890Smrg/* Put ourselves on the queue to read the connection. 2741ab64890Smrg Allocates and returns a queue element. */ 2751ab64890Smrg 2761ab64890Smrgstatic struct _XCVList * 2771ab64890Smrg_XPushReader( 2781ab64890Smrg Display *dpy, 2791ab64890Smrg struct _XCVList ***tail) 2801ab64890Smrg{ 2811ab64890Smrg struct _XCVList *cvl; 2821ab64890Smrg 2831ab64890Smrg cvl = _XCreateCVL(dpy); 2841ab64890Smrg#ifdef XTHREADS_DEBUG 2851ab64890Smrg printf("_XPushReader called in thread %x, pushing %x\n", 2861ab64890Smrg xthread_self(), cvl); 2871ab64890Smrg#endif 2881ab64890Smrg **tail = cvl; 2891ab64890Smrg *tail = &cvl->next; 2901ab64890Smrg return cvl; 2911ab64890Smrg} 2921ab64890Smrg 2931ab64890Smrg/* signal the next thread waiting to read the connection */ 2941ab64890Smrg 2951ab64890Smrgstatic void _XPopReader( 2961ab64890Smrg Display *dpy, 2971ab64890Smrg struct _XCVList **list, 2981ab64890Smrg struct _XCVList ***tail) 2991ab64890Smrg{ 3001ab64890Smrg register struct _XCVList *front = *list; 3011ab64890Smrg 3021ab64890Smrg#ifdef XTHREADS_DEBUG 3031ab64890Smrg printf("_XPopReader called in thread %x, popping %x\n", 3041ab64890Smrg xthread_self(), front); 3051ab64890Smrg#endif 3061ab64890Smrg 3071ab64890Smrg if (dpy->flags & XlibDisplayProcConni) 3081ab64890Smrg /* we never added ourself in the first place */ 3091ab64890Smrg return; 3101ab64890Smrg 3111ab64890Smrg if (front) { /* check "front" for paranoia */ 3121ab64890Smrg *list = front->next; 3131ab64890Smrg if (*tail == &front->next) /* did we free the last elt? */ 3141ab64890Smrg *tail = list; 3151ab64890Smrg if (dpy->lock->num_free_cvls < NUM_FREE_CVLS) { 3161ab64890Smrg front->next = dpy->lock->free_cvls; 3171ab64890Smrg dpy->lock->free_cvls = front; 3181ab64890Smrg dpy->lock->num_free_cvls++; 3191ab64890Smrg } else { 3201ab64890Smrg xcondition_clear(front->cv); 321818534a1Smrg Xfree(front->cv); 322818534a1Smrg Xfree(front); 3231ab64890Smrg } 3241ab64890Smrg } 3251ab64890Smrg 3261ab64890Smrg /* signal new front after it is in place */ 3271ab64890Smrg if ((dpy->lock->reply_first = (dpy->lock->reply_awaiters != NULL))) { 3281ab64890Smrg ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); 3291ab64890Smrg } else if (dpy->lock->event_awaiters) { 3301ab64890Smrg ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 3311ab64890Smrg } 3321ab64890Smrg} 3331ab64890Smrg 3341ab64890Smrgstatic void _XConditionWait( 3351ab64890Smrg xcondition_t cv, 3362e9c7c8cSmrg xmutex_t mutex 3372e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3382e9c7c8cSmrg ) 3391ab64890Smrg{ 3401ab64890Smrg#ifdef XTHREADS_WARN 3411ab64890Smrg xthread_t self = xthread_self(); 3421ab64890Smrg char *old_file = locking_file; 3431ab64890Smrg int old_line = locking_line; 34461b2299dSmrg 3451ab64890Smrg#ifdef XTHREADS_DEBUG 3461ab64890Smrg printf("line %d thread %x in condition wait\n", line, self); 3471ab64890Smrg#endif 3481ab64890Smrg xthread_clear_id(locking_thread); 3491ab64890Smrg 3501ab64890Smrg locking_history[lock_hist_loc].file = file; 3511ab64890Smrg locking_history[lock_hist_loc].line = line; 3521ab64890Smrg locking_history[lock_hist_loc].thread = self; 3531ab64890Smrg locking_history[lock_hist_loc].lockp = False; 3541ab64890Smrg lock_hist_loc++; 3551ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 3561ab64890Smrg lock_hist_loc = 0; 3571ab64890Smrg#endif /* XTHREADS_WARN */ 3581ab64890Smrg 3591ab64890Smrg xcondition_wait(cv, mutex); 3601ab64890Smrg 3611ab64890Smrg#ifdef XTHREADS_WARN 3621ab64890Smrg locking_thread = self; 3631ab64890Smrg locking_file = old_file; 3641ab64890Smrg locking_line = old_line; 3651ab64890Smrg 3661ab64890Smrg locking_history[lock_hist_loc].file = file; 3671ab64890Smrg locking_history[lock_hist_loc].line = line; 3681ab64890Smrg locking_history[lock_hist_loc].thread = self; 3691ab64890Smrg locking_history[lock_hist_loc].lockp = True; 3701ab64890Smrg lock_hist_loc++; 3711ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 3721ab64890Smrg lock_hist_loc = 0; 3731ab64890Smrg#ifdef XTHREADS_DEBUG 3741ab64890Smrg printf("line %d thread %x was signaled\n", line, self); 3751ab64890Smrg#endif /* XTHREADS_DEBUG */ 3761ab64890Smrg#endif /* XTHREADS_WARN */ 3771ab64890Smrg} 3781ab64890Smrg 3791ab64890Smrgstatic void _XConditionSignal( 3802e9c7c8cSmrg xcondition_t cv 3812e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3822e9c7c8cSmrg ) 3831ab64890Smrg{ 3841ab64890Smrg#ifdef XTHREADS_WARN 3851ab64890Smrg#ifdef XTHREADS_DEBUG 3861ab64890Smrg printf("line %d thread %x is signalling\n", line, xthread_self()); 3871ab64890Smrg#endif 3881ab64890Smrg#endif 3891ab64890Smrg xcondition_signal(cv); 3901ab64890Smrg} 39161b2299dSmrg 3921ab64890Smrg 3931ab64890Smrgstatic void _XConditionBroadcast( 3942e9c7c8cSmrg xcondition_t cv 3952e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3962e9c7c8cSmrg ) 3971ab64890Smrg{ 3981ab64890Smrg#ifdef XTHREADS_WARN 3991ab64890Smrg#ifdef XTHREADS_DEBUG 4001ab64890Smrg printf("line %d thread %x is broadcasting\n", line, xthread_self()); 4011ab64890Smrg#endif 4021ab64890Smrg#endif 4031ab64890Smrg xcondition_broadcast(cv); 4041ab64890Smrg} 40561b2299dSmrg 4061ab64890Smrg 4071ab64890Smrgstatic void _XFreeDisplayLock( 4081ab64890Smrg Display *dpy) 4091ab64890Smrg{ 4101ab64890Smrg struct _XCVList *cvl; 4111ab64890Smrg 4121ab64890Smrg if (dpy->lock != NULL) { 4131ab64890Smrg if (dpy->lock->mutex != NULL) { 4141ab64890Smrg xmutex_clear(dpy->lock->mutex); 4151ab64890Smrg xmutex_free(dpy->lock->mutex); 4161ab64890Smrg } 4171ab64890Smrg if (dpy->lock->cv != NULL) { 4181ab64890Smrg xcondition_clear(dpy->lock->cv); 4191ab64890Smrg xcondition_free(dpy->lock->cv); 4201ab64890Smrg } 4211ab64890Smrg if (dpy->lock->writers != NULL) { 4221ab64890Smrg xcondition_clear(dpy->lock->writers); 4231ab64890Smrg xcondition_free(dpy->lock->writers); 4241ab64890Smrg } 4251ab64890Smrg while ((cvl = dpy->lock->free_cvls)) { 4261ab64890Smrg dpy->lock->free_cvls = cvl->next; 4271ab64890Smrg xcondition_clear(cvl->cv); 428818534a1Smrg Xfree(cvl->cv); 429818534a1Smrg Xfree(cvl); 4301ab64890Smrg } 431818534a1Smrg Xfree(dpy->lock); 4321ab64890Smrg dpy->lock = NULL; 4331ab64890Smrg } 4341ab64890Smrg if (dpy->lock_fns != NULL) { 435818534a1Smrg Xfree(dpy->lock_fns); 4361ab64890Smrg dpy->lock_fns = NULL; 4371ab64890Smrg } 4381ab64890Smrg} 4391ab64890Smrg 4401ab64890Smrg/* 4411ab64890Smrg * wait for thread with user-level display lock to release it. 4421ab64890Smrg */ 4431ab64890Smrg 4441ab64890Smrgstatic void _XDisplayLockWait( 4451ab64890Smrg Display *dpy) 4461ab64890Smrg{ 4471ab64890Smrg xthread_t self; 4481ab64890Smrg 4491ab64890Smrg while (dpy->lock->locking_level > 0) { 4501ab64890Smrg self = xthread_self(); 4511ab64890Smrg if (xthread_equal(dpy->lock->locking_thread, self)) 4521ab64890Smrg break; 4531ab64890Smrg ConditionWait(dpy, dpy->lock->cv); 4541ab64890Smrg } 4551ab64890Smrg} 4561ab64890Smrg 4575efbdfc3Smrgstatic void _XLockDisplay( 4585efbdfc3Smrg Display *dpy 4595efbdfc3Smrg XTHREADS_FILE_LINE_ARGS 4605efbdfc3Smrg ) 4615efbdfc3Smrg{ 462876003caSmrg struct _XErrorThreadInfo *ti; 4635efbdfc3Smrg 464876003caSmrg if (dpy->in_ifevent && xthread_equal(dpy->ifevent_thread, xthread_self())) 465876003caSmrg return; 4660efe039aSmartin 4671ab64890Smrg#ifdef XTHREADS_WARN 4681ab64890Smrg _XLockDisplayWarn(dpy, file, line); 4691ab64890Smrg#else 4701ab64890Smrg xmutex_lock(dpy->lock->mutex); 4711ab64890Smrg#endif 472876003caSmrg 4731ab64890Smrg if (dpy->lock->locking_level > 0) 474876003caSmrg _XDisplayLockWait(dpy); 475876003caSmrg 476d4a3aaf4Smrg /* 477d4a3aaf4Smrg * Skip the two function calls below which may generate requests 478d4a3aaf4Smrg * when LockDisplay is called from within _XError. 479d4a3aaf4Smrg */ 480d4a3aaf4Smrg for (ti = dpy->error_threads; ti; ti = ti->next) 481d4a3aaf4Smrg if (ti->error_thread == xthread_self()) 482d4a3aaf4Smrg return; 483876003caSmrg 48488de56ccSmrg _XIDHandler(dpy); 48588de56ccSmrg _XSeqSyncFunction(dpy); 4861ab64890Smrg} 4871ab64890Smrg 4881ab64890Smrg/* 4891ab64890Smrg * _XReply is allowed to exit from select/poll and clean up even if a 4901ab64890Smrg * user-level lock is in force, so it uses this instead of _XFancyLockDisplay. 4911ab64890Smrg */ 4921ab64890Smrgstatic void _XInternalLockDisplay( 4931ab64890Smrg Display *dpy, 4942e9c7c8cSmrg Bool wskip 4952e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 4962e9c7c8cSmrg ) 4971ab64890Smrg{ 498876003caSmrg if (dpy->in_ifevent && xthread_equal(dpy->ifevent_thread, xthread_self())) 499876003caSmrg return; 500876003caSmrg 5011ab64890Smrg#ifdef XTHREADS_WARN 5021ab64890Smrg _XLockDisplayWarn(dpy, file, line); 5031ab64890Smrg#else 5041ab64890Smrg xmutex_lock(dpy->lock->mutex); 5051ab64890Smrg#endif 5061ab64890Smrg if (!wskip && dpy->lock->locking_level > 0) 5071ab64890Smrg _XDisplayLockWait(dpy); 5081ab64890Smrg} 5091ab64890Smrg 5101ab64890Smrgstatic void _XUserLockDisplay( 5111ab64890Smrg register Display* dpy) 5121ab64890Smrg{ 513eb411b4bSmrg _XDisplayLockWait(dpy); 514eb411b4bSmrg 5151ab64890Smrg if (++dpy->lock->locking_level == 1) { 5161ab64890Smrg dpy->lock->lock_wait = _XDisplayLockWait; 5171ab64890Smrg dpy->lock->locking_thread = xthread_self(); 5181ab64890Smrg } 5191ab64890Smrg} 5201ab64890Smrg 5211ab64890Smrgstatic 5221ab64890Smrgvoid _XUserUnlockDisplay( 5231ab64890Smrg register Display* dpy) 5241ab64890Smrg{ 5251ab64890Smrg if (dpy->lock->locking_level > 0 && --dpy->lock->locking_level == 0) { 5261ab64890Smrg /* signal other threads that might be waiting in XLockDisplay */ 5271ab64890Smrg ConditionBroadcast(dpy, dpy->lock->cv); 5281ab64890Smrg dpy->lock->lock_wait = NULL; 5291ab64890Smrg xthread_clear_id(dpy->lock->locking_thread); 5301ab64890Smrg } 5311ab64890Smrg} 5321ab64890Smrg 5331ab64890Smrg/* returns 0 if initialized ok, -1 if unable to allocate 5341ab64890Smrg a mutex or other memory */ 5351ab64890Smrg 5361ab64890Smrgstatic int _XInitDisplayLock( 5371ab64890Smrg Display *dpy) 5381ab64890Smrg{ 539eb411b4bSmrg dpy->lock_fns = Xmalloc(sizeof(struct _XLockPtrs)); 5401ab64890Smrg if (dpy->lock_fns == NULL) 5411ab64890Smrg return -1; 542eb411b4bSmrg dpy->lock = Xmalloc(sizeof(struct _XLockInfo)); 5431ab64890Smrg if (dpy->lock == NULL) { 5441ab64890Smrg _XFreeDisplayLock(dpy); 5451ab64890Smrg return -1; 5461ab64890Smrg } 5471ab64890Smrg dpy->lock->cv = xcondition_malloc(); 5481ab64890Smrg dpy->lock->mutex = xmutex_malloc(); 5491ab64890Smrg dpy->lock->writers = xcondition_malloc(); 5501ab64890Smrg if (!dpy->lock->cv || !dpy->lock->mutex || !dpy->lock->writers) { 5511ab64890Smrg _XFreeDisplayLock(dpy); 5521ab64890Smrg return -1; 5531ab64890Smrg } 5541ab64890Smrg 5551ab64890Smrg dpy->lock->reply_bytes_left = 0; 5561ab64890Smrg dpy->lock->reply_was_read = False; 5571ab64890Smrg dpy->lock->reply_awaiters = NULL; 5581ab64890Smrg dpy->lock->reply_awaiters_tail = &dpy->lock->reply_awaiters; 5591ab64890Smrg dpy->lock->event_awaiters = NULL; 5601ab64890Smrg dpy->lock->event_awaiters_tail = &dpy->lock->event_awaiters; 5611ab64890Smrg dpy->lock->reply_first = False; 5621ab64890Smrg dpy->lock->locking_level = 0; 5631ab64890Smrg dpy->lock->num_free_cvls = 0; 5641ab64890Smrg dpy->lock->free_cvls = NULL; 5651ab64890Smrg xthread_clear_id(dpy->lock->locking_thread); 5661ab64890Smrg xthread_clear_id(dpy->lock->reading_thread); 5671ab64890Smrg xthread_clear_id(dpy->lock->conni_thread); 5681ab64890Smrg xmutex_init(dpy->lock->mutex); 5691ab64890Smrg xmutex_set_name(dpy->lock->mutex, "Xlib Display"); 5701ab64890Smrg xcondition_init(dpy->lock->cv); 5711ab64890Smrg xcondition_set_name(dpy->lock->cv, "XLockDisplay"); 5721ab64890Smrg xcondition_init(dpy->lock->writers); 5731ab64890Smrg xcondition_set_name(dpy->lock->writers, "Xlib wait for writable"); 5741ab64890Smrg dpy->lock_fns->lock_display = _XLockDisplay; 5751ab64890Smrg dpy->lock->internal_lock_display = _XInternalLockDisplay; 5761ab64890Smrg dpy->lock_fns->unlock_display = _XUnlockDisplay; 5771ab64890Smrg dpy->lock->user_lock_display = _XUserLockDisplay; 5781ab64890Smrg dpy->lock->user_unlock_display = _XUserUnlockDisplay; 5791ab64890Smrg dpy->lock->pop_reader = _XPopReader; 5801ab64890Smrg dpy->lock->push_reader = _XPushReader; 5811ab64890Smrg dpy->lock->condition_wait = _XConditionWait; 5821ab64890Smrg dpy->lock->condition_signal = _XConditionSignal; 5831ab64890Smrg dpy->lock->condition_broadcast = _XConditionBroadcast; 5841ab64890Smrg dpy->lock->create_cvl = _XCreateCVL; 5851ab64890Smrg dpy->lock->lock_wait = NULL; /* filled in by XLockDisplay() */ 5861ab64890Smrg 5871ab64890Smrg return 0; 5881ab64890Smrg} 5891ab64890Smrg 5901ab64890Smrg#ifdef __UNIXWARE__ 5911ab64890Smrgxthread_t __x11_thr_self() { return 0; } 5921ab64890Smrgxthread_t (*_x11_thr_self)() = __x11_thr_self; 5931ab64890Smrg#endif 5941ab64890Smrg 5951ab64890Smrg 59661b2299dSmrgStatus XInitThreads(void) 5971ab64890Smrg{ 5981ab64890Smrg if (_Xglobal_lock) 5991ab64890Smrg return 1; 6001ab64890Smrg#ifdef __UNIXWARE__ 6011ab64890Smrg else { 6021ab64890Smrg void *dl_handle = dlopen(NULL, RTLD_LAZY); 6031ab64890Smrg if (!dl_handle || 6041ab64890Smrg ((_x11_thr_self = (xthread_t(*)())dlsym(dl_handle,"thr_self")) == 0)) { 6051ab64890Smrg _x11_thr_self = __x11_thr_self; 6061ab64890Smrg (void) fprintf (stderr, 6071ab64890Smrg "XInitThreads called, but no libthread in the calling program!\n" ); 6081ab64890Smrg } 6091ab64890Smrg } 6101ab64890Smrg#endif /* __UNIXWARE__ */ 6111ab64890Smrg#ifdef xthread_init 6121ab64890Smrg xthread_init(); /* return value? */ 6131ab64890Smrg#endif 6141ab64890Smrg if (!(global_lock.lock = xmutex_malloc())) 6151ab64890Smrg return 0; 6161ab64890Smrg if (!(i18n_lock.lock = xmutex_malloc())) { 6171ab64890Smrg xmutex_free(global_lock.lock); 6181ab64890Smrg global_lock.lock = NULL; 6191ab64890Smrg return 0; 6201ab64890Smrg } 621d4a3aaf4Smrg if (!(conv_lock.lock = xmutex_malloc())) { 622d4a3aaf4Smrg xmutex_free(global_lock.lock); 623d4a3aaf4Smrg global_lock.lock = NULL; 624d4a3aaf4Smrg xmutex_free(i18n_lock.lock); 625d4a3aaf4Smrg i18n_lock.lock = NULL; 626d4a3aaf4Smrg return 0; 627d4a3aaf4Smrg } 6281ab64890Smrg _Xglobal_lock = &global_lock; 6291ab64890Smrg xmutex_init(_Xglobal_lock->lock); 6301ab64890Smrg xmutex_set_name(_Xglobal_lock->lock, "Xlib global"); 6311ab64890Smrg _Xi18n_lock = &i18n_lock; 6321ab64890Smrg xmutex_init(_Xi18n_lock->lock); 6331ab64890Smrg xmutex_set_name(_Xi18n_lock->lock, "Xlib i18n"); 634d4a3aaf4Smrg _conv_lock = &conv_lock; 635d4a3aaf4Smrg xmutex_init(_conv_lock->lock); 636d4a3aaf4Smrg xmutex_set_name(_conv_lock->lock, "Xlib conv"); 6371ab64890Smrg _XLockMutex_fn = _XLockMutex; 6381ab64890Smrg _XUnlockMutex_fn = _XUnlockMutex; 6391ab64890Smrg _XCreateMutex_fn = _XCreateMutex; 6401ab64890Smrg _XFreeMutex_fn = _XFreeMutex; 6411ab64890Smrg _XInitDisplayLock_fn = _XInitDisplayLock; 6421ab64890Smrg _XFreeDisplayLock_fn = _XFreeDisplayLock; 6431ab64890Smrg _Xthread_self_fn = _Xthread_self; 6441ab64890Smrg 6451ab64890Smrg#ifdef XTHREADS_WARN 6461ab64890Smrg#ifdef XTHREADS_DEBUG 6471ab64890Smrg setlinebuf(stdout); /* for debugging messages */ 6481ab64890Smrg#endif 6491ab64890Smrg#endif 6501ab64890Smrg 6511ab64890Smrg return 1; 6521ab64890Smrg} 6531ab64890Smrg 6540efe039aSmartinStatus XFreeThreads(void) 6550efe039aSmartin{ 6560efe039aSmartin if (global_lock.lock != NULL) { 6570efe039aSmartin xmutex_free(global_lock.lock); 6580efe039aSmartin global_lock.lock = NULL; 6590efe039aSmartin } 6600efe039aSmartin if (i18n_lock.lock != NULL) { 6610efe039aSmartin xmutex_free(i18n_lock.lock); 6620efe039aSmartin i18n_lock.lock = NULL; 6630efe039aSmartin } 6640efe039aSmartin if (conv_lock.lock != NULL) { 6650efe039aSmartin xmutex_free(conv_lock.lock); 6660efe039aSmartin conv_lock.lock = NULL; 6670efe039aSmartin } 6680efe039aSmartin 6690efe039aSmartin return 1; 6700efe039aSmartin} 6710efe039aSmartin 6721ab64890Smrg#else /* XTHREADS */ 6732e9c7c8cSmrgStatus XInitThreads(void) 6741ab64890Smrg{ 6751ab64890Smrg return 0; 6761ab64890Smrg} 6770efe039aSmartin 6780efe039aSmartinStatus XFreeThreads(void) 6790efe039aSmartin{ 6800efe039aSmartin return 0; 6810efe039aSmartin} 6821ab64890Smrg#endif /* XTHREADS */ 683