locking.c revision 88de56cc
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; 691ab64890Smrg 701ab64890Smrg#ifdef WIN32 711ab64890Smrgstatic DWORD _X_TlsIndex = (DWORD)-1; 721ab64890Smrg 732e9c7c8cSmrgvoid _Xthread_init(void) 741ab64890Smrg{ 751ab64890Smrg if (_X_TlsIndex == (DWORD)-1) 761ab64890Smrg _X_TlsIndex = TlsAlloc(); 771ab64890Smrg} 781ab64890Smrg 791ab64890Smrgstruct _xthread_waiter * 802e9c7c8cSmrg_Xthread_waiter(void) 811ab64890Smrg{ 821ab64890Smrg struct _xthread_waiter *me; 831ab64890Smrg 841ab64890Smrg if (!(me = TlsGetValue(_X_TlsIndex))) { 851ab64890Smrg me = (struct _xthread_waiter *)xmalloc(sizeof(struct _xthread_waiter)); 861ab64890Smrg me->sem = CreateSemaphore(NULL, 0, 1, NULL); 871ab64890Smrg me->next = NULL; 881ab64890Smrg TlsSetValue(_X_TlsIndex, me); 891ab64890Smrg } 901ab64890Smrg return me; 911ab64890Smrg} 921ab64890Smrg#endif /* WIN32 */ 931ab64890Smrg 941ab64890Smrgstatic xthread_t _Xthread_self(void) 951ab64890Smrg{ 961ab64890Smrg return xthread_self(); 971ab64890Smrg} 981ab64890Smrg 991ab64890Smrgstatic LockInfoRec global_lock; 1001ab64890Smrgstatic LockInfoRec i18n_lock; 1011ab64890Smrg 1021ab64890Smrgstatic void _XLockMutex( 1032e9c7c8cSmrg LockInfoPtr lip 1042e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 1052e9c7c8cSmrg ) 1061ab64890Smrg{ 1071ab64890Smrg xmutex_lock(lip->lock); 1081ab64890Smrg} 1091ab64890Smrg 1101ab64890Smrgstatic void _XUnlockMutex( 1112e9c7c8cSmrg LockInfoPtr lip 1122e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 1132e9c7c8cSmrg ) 1141ab64890Smrg{ 1151ab64890Smrg xmutex_unlock(lip->lock); 1161ab64890Smrg} 1171ab64890Smrg 1181ab64890Smrgstatic void _XCreateMutex( 1191ab64890Smrg LockInfoPtr lip) 1201ab64890Smrg{ 1211ab64890Smrg lip->lock = xmutex_malloc(); 1221ab64890Smrg if (lip->lock) { 1231ab64890Smrg xmutex_init(lip->lock); 1241ab64890Smrg xmutex_set_name(lip->lock, "Xlib"); 1251ab64890Smrg } 1261ab64890Smrg} 1271ab64890Smrg 1281ab64890Smrgstatic void _XFreeMutex( 1291ab64890Smrg LockInfoPtr lip) 1301ab64890Smrg{ 1311ab64890Smrg xmutex_clear(lip->lock); 1321ab64890Smrg xmutex_free(lip->lock); 1331ab64890Smrg} 1341ab64890Smrg 1351ab64890Smrg#ifdef XTHREADS_WARN 1361ab64890Smrgstatic char *locking_file; 1371ab64890Smrgstatic int locking_line; 1381ab64890Smrgstatic xthread_t locking_thread; 1391ab64890Smrgstatic Bool xlibint_unlock = False; /* XlibInt.c may Unlock and re-Lock */ 1401ab64890Smrg 1411ab64890Smrg/* history that is useful to examine in a debugger */ 1421ab64890Smrg#define LOCK_HIST_SIZE 21 1431ab64890Smrg 1441ab64890Smrgstatic struct { 1451ab64890Smrg Bool lockp; /* True for lock, False for unlock */ 1461ab64890Smrg xthread_t thread; 1471ab64890Smrg char *file; 1481ab64890Smrg int line; 1491ab64890Smrg} locking_history[LOCK_HIST_SIZE]; 1501ab64890Smrg 1511ab64890Smrgint lock_hist_loc = 0; /* next slot to fill */ 1521ab64890Smrg 1531ab64890Smrgstatic void _XLockDisplayWarn( 1541ab64890Smrg Display *dpy, 1551ab64890Smrg char *file, /* source file, from macro */ 1561ab64890Smrg int line) 1571ab64890Smrg{ 1581ab64890Smrg xthread_t self; 1591ab64890Smrg xthread_t old_locker; 1601ab64890Smrg 1611ab64890Smrg self = xthread_self(); 1621ab64890Smrg old_locker = locking_thread; 1631ab64890Smrg if (xthread_have_id(old_locker)) { 1641ab64890Smrg if (xthread_equal(old_locker, self)) 1651ab64890Smrg printf("Xlib ERROR: %s line %d thread %x: locking display already locked at %s line %d\n", 1661ab64890Smrg file, line, self, locking_file, locking_line); 1671ab64890Smrg#ifdef XTHREADS_DEBUG 1681ab64890Smrg else 1691ab64890Smrg printf("%s line %d: thread %x waiting on lock held by %s line %d thread %x\n", 1701ab64890Smrg file, line, self, 1711ab64890Smrg locking_file, locking_line, old_locker); 1721ab64890Smrg#endif /* XTHREADS_DEBUG */ 1731ab64890Smrg } 1741ab64890Smrg 1751ab64890Smrg xmutex_lock(dpy->lock->mutex); 1761ab64890Smrg 1771ab64890Smrg if (strcmp(file, "XlibInt.c") == 0) { 1781ab64890Smrg if (!xlibint_unlock) 1791ab64890Smrg printf("Xlib ERROR: XlibInt.c line %d thread %x locking display it did not unlock\n", 1801ab64890Smrg line, self); 1811ab64890Smrg xlibint_unlock = False; 1821ab64890Smrg } 1831ab64890Smrg 1841ab64890Smrg#ifdef XTHREADS_DEBUG 1851ab64890Smrg /* if (old_locker && old_locker != self) */ 1861ab64890Smrg if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ 1871ab64890Smrg printf("%s line %d: thread %x got display lock\n", file, line, self); 1881ab64890Smrg#endif /* XTHREADS_DEBUG */ 1891ab64890Smrg 1901ab64890Smrg locking_thread = self; 1911ab64890Smrg if (strcmp(file, "XlibInt.c") != 0) { 1921ab64890Smrg locking_file = file; 1931ab64890Smrg locking_line = line; 1941ab64890Smrg } 1951ab64890Smrg locking_history[lock_hist_loc].file = file; 1961ab64890Smrg locking_history[lock_hist_loc].line = line; 1971ab64890Smrg locking_history[lock_hist_loc].thread = self; 1981ab64890Smrg locking_history[lock_hist_loc].lockp = True; 1991ab64890Smrg lock_hist_loc++; 2001ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 2011ab64890Smrg lock_hist_loc = 0; 2021ab64890Smrg} 2031ab64890Smrg#endif /* XTHREADS_WARN */ 2041ab64890Smrg 2051ab64890Smrgstatic void _XUnlockDisplay( 2062e9c7c8cSmrg Display *dpy 2072e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 2082e9c7c8cSmrg ) 2091ab64890Smrg{ 2101ab64890Smrg#ifdef XTHREADS_WARN 2111ab64890Smrg xthread_t self = xthread_self(); 2121ab64890Smrg 2131ab64890Smrg#ifdef XTHREADS_DEBUG 2141ab64890Smrg if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ 2151ab64890Smrg printf("%s line %d: thread %x unlocking display\n", file, line, self); 2161ab64890Smrg#endif /* XTHREADS_DEBUG */ 2171ab64890Smrg 2181ab64890Smrg if (!xthread_have_id(locking_thread)) 2191ab64890Smrg printf("Xlib ERROR: %s line %d thread %x: unlocking display that is not locked\n", 2201ab64890Smrg file, line, self); 2211ab64890Smrg else if (strcmp(file, "XlibInt.c") == 0) 2221ab64890Smrg xlibint_unlock = True; 2231ab64890Smrg#ifdef XTHREADS_DEBUG 2241ab64890Smrg else if (strcmp(file, locking_file) != 0) 2251ab64890Smrg /* not always an error because locking_file is not per-thread */ 2261ab64890Smrg printf("%s line %d: unlocking display locked from %s line %d (probably okay)\n", 2271ab64890Smrg file, line, locking_file, locking_line); 2281ab64890Smrg#endif /* XTHREADS_DEBUG */ 2291ab64890Smrg xthread_clear_id(locking_thread); 2301ab64890Smrg 2311ab64890Smrg locking_history[lock_hist_loc].file = file; 2321ab64890Smrg locking_history[lock_hist_loc].line = line; 2331ab64890Smrg locking_history[lock_hist_loc].thread = self; 2341ab64890Smrg locking_history[lock_hist_loc].lockp = False; 2351ab64890Smrg lock_hist_loc++; 2361ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 2371ab64890Smrg lock_hist_loc = 0; 2381ab64890Smrg#endif /* XTHREADS_WARN */ 2391ab64890Smrg xmutex_unlock(dpy->lock->mutex); 2401ab64890Smrg} 2411ab64890Smrg 2421ab64890Smrg 2431ab64890Smrgstatic struct _XCVList *_XCreateCVL( 2441ab64890Smrg Display *dpy) 2451ab64890Smrg{ 2461ab64890Smrg struct _XCVList *cvl; 2471ab64890Smrg 2481ab64890Smrg if ((cvl = dpy->lock->free_cvls) != NULL) { 2491ab64890Smrg dpy->lock->free_cvls = cvl->next; 2501ab64890Smrg dpy->lock->num_free_cvls--; 2511ab64890Smrg } else { 2521ab64890Smrg cvl = (struct _XCVList *)Xmalloc(sizeof(struct _XCVList)); 2531ab64890Smrg if (!cvl) 2541ab64890Smrg return NULL; 2551ab64890Smrg cvl->cv = xcondition_malloc(); 2561ab64890Smrg if (!cvl->cv) { 2571ab64890Smrg Xfree(cvl); 2581ab64890Smrg return NULL; 2591ab64890Smrg } 2601ab64890Smrg xcondition_init(cvl->cv); 2611ab64890Smrg xcondition_set_name(cvl->cv, "Xlib read queue"); 2621ab64890Smrg } 2631ab64890Smrg cvl->next = NULL; 2641ab64890Smrg return cvl; 2651ab64890Smrg} 2661ab64890Smrg 2671ab64890Smrg/* Put ourselves on the queue to read the connection. 2681ab64890Smrg Allocates and returns a queue element. */ 2691ab64890Smrg 2701ab64890Smrgstatic struct _XCVList * 2711ab64890Smrg_XPushReader( 2721ab64890Smrg Display *dpy, 2731ab64890Smrg struct _XCVList ***tail) 2741ab64890Smrg{ 2751ab64890Smrg struct _XCVList *cvl; 2761ab64890Smrg 2771ab64890Smrg cvl = _XCreateCVL(dpy); 2781ab64890Smrg#ifdef XTHREADS_DEBUG 2791ab64890Smrg printf("_XPushReader called in thread %x, pushing %x\n", 2801ab64890Smrg xthread_self(), cvl); 2811ab64890Smrg#endif 2821ab64890Smrg **tail = cvl; 2831ab64890Smrg *tail = &cvl->next; 2841ab64890Smrg return cvl; 2851ab64890Smrg} 2861ab64890Smrg 2871ab64890Smrg/* signal the next thread waiting to read the connection */ 2881ab64890Smrg 2891ab64890Smrgstatic void _XPopReader( 2901ab64890Smrg Display *dpy, 2911ab64890Smrg struct _XCVList **list, 2921ab64890Smrg struct _XCVList ***tail) 2931ab64890Smrg{ 2941ab64890Smrg register struct _XCVList *front = *list; 2951ab64890Smrg 2961ab64890Smrg#ifdef XTHREADS_DEBUG 2971ab64890Smrg printf("_XPopReader called in thread %x, popping %x\n", 2981ab64890Smrg xthread_self(), front); 2991ab64890Smrg#endif 3001ab64890Smrg 3011ab64890Smrg if (dpy->flags & XlibDisplayProcConni) 3021ab64890Smrg /* we never added ourself in the first place */ 3031ab64890Smrg return; 3041ab64890Smrg 3051ab64890Smrg if (front) { /* check "front" for paranoia */ 3061ab64890Smrg *list = front->next; 3071ab64890Smrg if (*tail == &front->next) /* did we free the last elt? */ 3081ab64890Smrg *tail = list; 3091ab64890Smrg if (dpy->lock->num_free_cvls < NUM_FREE_CVLS) { 3101ab64890Smrg front->next = dpy->lock->free_cvls; 3111ab64890Smrg dpy->lock->free_cvls = front; 3121ab64890Smrg dpy->lock->num_free_cvls++; 3131ab64890Smrg } else { 3141ab64890Smrg xcondition_clear(front->cv); 3151ab64890Smrg Xfree((char *)front->cv); 3161ab64890Smrg Xfree((char *)front); 3171ab64890Smrg } 3181ab64890Smrg } 3191ab64890Smrg 3201ab64890Smrg /* signal new front after it is in place */ 3211ab64890Smrg if ((dpy->lock->reply_first = (dpy->lock->reply_awaiters != NULL))) { 3221ab64890Smrg ConditionSignal(dpy, dpy->lock->reply_awaiters->cv); 3231ab64890Smrg } else if (dpy->lock->event_awaiters) { 3241ab64890Smrg ConditionSignal(dpy, dpy->lock->event_awaiters->cv); 3251ab64890Smrg } 3261ab64890Smrg} 3271ab64890Smrg 3281ab64890Smrgstatic void _XConditionWait( 3291ab64890Smrg xcondition_t cv, 3302e9c7c8cSmrg xmutex_t mutex 3312e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3322e9c7c8cSmrg ) 3331ab64890Smrg{ 3341ab64890Smrg#ifdef XTHREADS_WARN 3351ab64890Smrg xthread_t self = xthread_self(); 3361ab64890Smrg char *old_file = locking_file; 3371ab64890Smrg int old_line = locking_line; 33861b2299dSmrg 3391ab64890Smrg#ifdef XTHREADS_DEBUG 3401ab64890Smrg printf("line %d thread %x in condition wait\n", line, self); 3411ab64890Smrg#endif 3421ab64890Smrg xthread_clear_id(locking_thread); 3431ab64890Smrg 3441ab64890Smrg locking_history[lock_hist_loc].file = file; 3451ab64890Smrg locking_history[lock_hist_loc].line = line; 3461ab64890Smrg locking_history[lock_hist_loc].thread = self; 3471ab64890Smrg locking_history[lock_hist_loc].lockp = False; 3481ab64890Smrg lock_hist_loc++; 3491ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 3501ab64890Smrg lock_hist_loc = 0; 3511ab64890Smrg#endif /* XTHREADS_WARN */ 3521ab64890Smrg 3531ab64890Smrg xcondition_wait(cv, mutex); 3541ab64890Smrg 3551ab64890Smrg#ifdef XTHREADS_WARN 3561ab64890Smrg locking_thread = self; 3571ab64890Smrg locking_file = old_file; 3581ab64890Smrg locking_line = old_line; 3591ab64890Smrg 3601ab64890Smrg locking_history[lock_hist_loc].file = file; 3611ab64890Smrg locking_history[lock_hist_loc].line = line; 3621ab64890Smrg locking_history[lock_hist_loc].thread = self; 3631ab64890Smrg locking_history[lock_hist_loc].lockp = True; 3641ab64890Smrg lock_hist_loc++; 3651ab64890Smrg if (lock_hist_loc >= LOCK_HIST_SIZE) 3661ab64890Smrg lock_hist_loc = 0; 3671ab64890Smrg#ifdef XTHREADS_DEBUG 3681ab64890Smrg printf("line %d thread %x was signaled\n", line, self); 3691ab64890Smrg#endif /* XTHREADS_DEBUG */ 3701ab64890Smrg#endif /* XTHREADS_WARN */ 3711ab64890Smrg} 3721ab64890Smrg 3731ab64890Smrgstatic void _XConditionSignal( 3742e9c7c8cSmrg xcondition_t cv 3752e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3762e9c7c8cSmrg ) 3771ab64890Smrg{ 3781ab64890Smrg#ifdef XTHREADS_WARN 3791ab64890Smrg#ifdef XTHREADS_DEBUG 3801ab64890Smrg printf("line %d thread %x is signalling\n", line, xthread_self()); 3811ab64890Smrg#endif 3821ab64890Smrg#endif 3831ab64890Smrg xcondition_signal(cv); 3841ab64890Smrg} 38561b2299dSmrg 3861ab64890Smrg 3871ab64890Smrgstatic void _XConditionBroadcast( 3882e9c7c8cSmrg xcondition_t cv 3892e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 3902e9c7c8cSmrg ) 3911ab64890Smrg{ 3921ab64890Smrg#ifdef XTHREADS_WARN 3931ab64890Smrg#ifdef XTHREADS_DEBUG 3941ab64890Smrg printf("line %d thread %x is broadcasting\n", line, xthread_self()); 3951ab64890Smrg#endif 3961ab64890Smrg#endif 3971ab64890Smrg xcondition_broadcast(cv); 3981ab64890Smrg} 39961b2299dSmrg 4001ab64890Smrg 4011ab64890Smrgstatic void _XFreeDisplayLock( 4021ab64890Smrg Display *dpy) 4031ab64890Smrg{ 4041ab64890Smrg struct _XCVList *cvl; 4051ab64890Smrg 4061ab64890Smrg if (dpy->lock != NULL) { 4071ab64890Smrg if (dpy->lock->mutex != NULL) { 4081ab64890Smrg xmutex_clear(dpy->lock->mutex); 4091ab64890Smrg xmutex_free(dpy->lock->mutex); 4101ab64890Smrg } 4111ab64890Smrg if (dpy->lock->cv != NULL) { 4121ab64890Smrg xcondition_clear(dpy->lock->cv); 4131ab64890Smrg xcondition_free(dpy->lock->cv); 4141ab64890Smrg } 4151ab64890Smrg if (dpy->lock->writers != NULL) { 4161ab64890Smrg xcondition_clear(dpy->lock->writers); 4171ab64890Smrg xcondition_free(dpy->lock->writers); 4181ab64890Smrg } 4191ab64890Smrg while ((cvl = dpy->lock->free_cvls)) { 4201ab64890Smrg dpy->lock->free_cvls = cvl->next; 4211ab64890Smrg xcondition_clear(cvl->cv); 4221ab64890Smrg Xfree((char *)cvl->cv); 4231ab64890Smrg Xfree((char *)cvl); 4241ab64890Smrg } 4251ab64890Smrg Xfree((char *)dpy->lock); 4261ab64890Smrg dpy->lock = NULL; 4271ab64890Smrg } 4281ab64890Smrg if (dpy->lock_fns != NULL) { 4291ab64890Smrg Xfree((char *)dpy->lock_fns); 4301ab64890Smrg dpy->lock_fns = NULL; 4311ab64890Smrg } 4321ab64890Smrg} 4331ab64890Smrg 4341ab64890Smrg/* 4351ab64890Smrg * wait for thread with user-level display lock to release it. 4361ab64890Smrg */ 4371ab64890Smrg 4381ab64890Smrgstatic void _XDisplayLockWait( 4391ab64890Smrg Display *dpy) 4401ab64890Smrg{ 4411ab64890Smrg xthread_t self; 4421ab64890Smrg 4431ab64890Smrg while (dpy->lock->locking_level > 0) { 4441ab64890Smrg self = xthread_self(); 4451ab64890Smrg if (xthread_equal(dpy->lock->locking_thread, self)) 4461ab64890Smrg break; 4471ab64890Smrg ConditionWait(dpy, dpy->lock->cv); 4481ab64890Smrg } 4491ab64890Smrg} 4501ab64890Smrg 4511ab64890Smrgstatic void _XLockDisplay( 4522e9c7c8cSmrg Display *dpy 4532e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 4542e9c7c8cSmrg ) 4551ab64890Smrg{ 4561ab64890Smrg#ifdef XTHREADS_WARN 4571ab64890Smrg _XLockDisplayWarn(dpy, file, line); 4581ab64890Smrg#else 4591ab64890Smrg xmutex_lock(dpy->lock->mutex); 4601ab64890Smrg#endif 4611ab64890Smrg if (dpy->lock->locking_level > 0) 4621ab64890Smrg _XDisplayLockWait(dpy); 46388de56ccSmrg _XIDHandler(dpy); 46488de56ccSmrg _XSeqSyncFunction(dpy); 4651ab64890Smrg} 4661ab64890Smrg 4671ab64890Smrg/* 4681ab64890Smrg * _XReply is allowed to exit from select/poll and clean up even if a 4691ab64890Smrg * user-level lock is in force, so it uses this instead of _XFancyLockDisplay. 4701ab64890Smrg */ 4711ab64890Smrgstatic void _XInternalLockDisplay( 4721ab64890Smrg Display *dpy, 4732e9c7c8cSmrg Bool wskip 4742e9c7c8cSmrg XTHREADS_FILE_LINE_ARGS 4752e9c7c8cSmrg ) 4761ab64890Smrg{ 4771ab64890Smrg#ifdef XTHREADS_WARN 4781ab64890Smrg _XLockDisplayWarn(dpy, file, line); 4791ab64890Smrg#else 4801ab64890Smrg xmutex_lock(dpy->lock->mutex); 4811ab64890Smrg#endif 4821ab64890Smrg if (!wskip && dpy->lock->locking_level > 0) 4831ab64890Smrg _XDisplayLockWait(dpy); 4841ab64890Smrg} 4851ab64890Smrg 4861ab64890Smrgstatic void _XUserLockDisplay( 4871ab64890Smrg register Display* dpy) 4881ab64890Smrg{ 4891ab64890Smrg if (++dpy->lock->locking_level == 1) { 4901ab64890Smrg dpy->lock->lock_wait = _XDisplayLockWait; 4911ab64890Smrg dpy->lock->locking_thread = xthread_self(); 4921ab64890Smrg } 4931ab64890Smrg} 4941ab64890Smrg 4951ab64890Smrgstatic 4961ab64890Smrgvoid _XUserUnlockDisplay( 4971ab64890Smrg register Display* dpy) 4981ab64890Smrg{ 4991ab64890Smrg if (dpy->lock->locking_level > 0 && --dpy->lock->locking_level == 0) { 5001ab64890Smrg /* signal other threads that might be waiting in XLockDisplay */ 5011ab64890Smrg ConditionBroadcast(dpy, dpy->lock->cv); 5021ab64890Smrg dpy->lock->lock_wait = NULL; 5031ab64890Smrg xthread_clear_id(dpy->lock->locking_thread); 5041ab64890Smrg } 5051ab64890Smrg} 5061ab64890Smrg 5071ab64890Smrg/* returns 0 if initialized ok, -1 if unable to allocate 5081ab64890Smrg a mutex or other memory */ 5091ab64890Smrg 5101ab64890Smrgstatic int _XInitDisplayLock( 5111ab64890Smrg Display *dpy) 5121ab64890Smrg{ 5131ab64890Smrg dpy->lock_fns = (struct _XLockPtrs*)Xmalloc(sizeof(struct _XLockPtrs)); 5141ab64890Smrg if (dpy->lock_fns == NULL) 5151ab64890Smrg return -1; 5161ab64890Smrg dpy->lock = (struct _XLockInfo *)Xmalloc(sizeof(struct _XLockInfo)); 5171ab64890Smrg if (dpy->lock == NULL) { 5181ab64890Smrg _XFreeDisplayLock(dpy); 5191ab64890Smrg return -1; 5201ab64890Smrg } 5211ab64890Smrg dpy->lock->cv = xcondition_malloc(); 5221ab64890Smrg dpy->lock->mutex = xmutex_malloc(); 5231ab64890Smrg dpy->lock->writers = xcondition_malloc(); 5241ab64890Smrg if (!dpy->lock->cv || !dpy->lock->mutex || !dpy->lock->writers) { 5251ab64890Smrg _XFreeDisplayLock(dpy); 5261ab64890Smrg return -1; 5271ab64890Smrg } 5281ab64890Smrg 5291ab64890Smrg dpy->lock->reply_bytes_left = 0; 5301ab64890Smrg dpy->lock->reply_was_read = False; 5311ab64890Smrg dpy->lock->reply_awaiters = NULL; 5321ab64890Smrg dpy->lock->reply_awaiters_tail = &dpy->lock->reply_awaiters; 5331ab64890Smrg dpy->lock->event_awaiters = NULL; 5341ab64890Smrg dpy->lock->event_awaiters_tail = &dpy->lock->event_awaiters; 5351ab64890Smrg dpy->lock->reply_first = False; 5361ab64890Smrg dpy->lock->locking_level = 0; 5371ab64890Smrg dpy->lock->num_free_cvls = 0; 5381ab64890Smrg dpy->lock->free_cvls = NULL; 5391ab64890Smrg xthread_clear_id(dpy->lock->locking_thread); 5401ab64890Smrg xthread_clear_id(dpy->lock->reading_thread); 5411ab64890Smrg xthread_clear_id(dpy->lock->conni_thread); 5421ab64890Smrg xmutex_init(dpy->lock->mutex); 5431ab64890Smrg xmutex_set_name(dpy->lock->mutex, "Xlib Display"); 5441ab64890Smrg xcondition_init(dpy->lock->cv); 5451ab64890Smrg xcondition_set_name(dpy->lock->cv, "XLockDisplay"); 5461ab64890Smrg xcondition_init(dpy->lock->writers); 5471ab64890Smrg xcondition_set_name(dpy->lock->writers, "Xlib wait for writable"); 5481ab64890Smrg dpy->lock_fns->lock_display = _XLockDisplay; 5491ab64890Smrg dpy->lock->internal_lock_display = _XInternalLockDisplay; 5501ab64890Smrg dpy->lock_fns->unlock_display = _XUnlockDisplay; 5511ab64890Smrg dpy->lock->user_lock_display = _XUserLockDisplay; 5521ab64890Smrg dpy->lock->user_unlock_display = _XUserUnlockDisplay; 5531ab64890Smrg dpy->lock->pop_reader = _XPopReader; 5541ab64890Smrg dpy->lock->push_reader = _XPushReader; 5551ab64890Smrg dpy->lock->condition_wait = _XConditionWait; 5561ab64890Smrg dpy->lock->condition_signal = _XConditionSignal; 5571ab64890Smrg dpy->lock->condition_broadcast = _XConditionBroadcast; 5581ab64890Smrg dpy->lock->create_cvl = _XCreateCVL; 5591ab64890Smrg dpy->lock->lock_wait = NULL; /* filled in by XLockDisplay() */ 5601ab64890Smrg 5611ab64890Smrg return 0; 5621ab64890Smrg} 5631ab64890Smrg 5641ab64890Smrg#ifdef __UNIXWARE__ 5651ab64890Smrgxthread_t __x11_thr_self() { return 0; } 5661ab64890Smrgxthread_t (*_x11_thr_self)() = __x11_thr_self; 5671ab64890Smrg#endif 5681ab64890Smrg 5691ab64890Smrg 57061b2299dSmrgStatus XInitThreads(void) 5711ab64890Smrg{ 5721ab64890Smrg if (_Xglobal_lock) 5731ab64890Smrg return 1; 5741ab64890Smrg#ifdef __UNIXWARE__ 5751ab64890Smrg else { 5761ab64890Smrg void *dl_handle = dlopen(NULL, RTLD_LAZY); 5771ab64890Smrg if (!dl_handle || 5781ab64890Smrg ((_x11_thr_self = (xthread_t(*)())dlsym(dl_handle,"thr_self")) == 0)) { 5791ab64890Smrg _x11_thr_self = __x11_thr_self; 5801ab64890Smrg (void) fprintf (stderr, 5811ab64890Smrg "XInitThreads called, but no libthread in the calling program!\n" ); 5821ab64890Smrg } 5831ab64890Smrg } 5841ab64890Smrg#endif /* __UNIXWARE__ */ 5851ab64890Smrg#ifdef xthread_init 5861ab64890Smrg xthread_init(); /* return value? */ 5871ab64890Smrg#endif 5881ab64890Smrg if (!(global_lock.lock = xmutex_malloc())) 5891ab64890Smrg return 0; 5901ab64890Smrg if (!(i18n_lock.lock = xmutex_malloc())) { 5911ab64890Smrg xmutex_free(global_lock.lock); 5921ab64890Smrg global_lock.lock = NULL; 5931ab64890Smrg return 0; 5941ab64890Smrg } 5951ab64890Smrg _Xglobal_lock = &global_lock; 5961ab64890Smrg xmutex_init(_Xglobal_lock->lock); 5971ab64890Smrg xmutex_set_name(_Xglobal_lock->lock, "Xlib global"); 5981ab64890Smrg _Xi18n_lock = &i18n_lock; 5991ab64890Smrg xmutex_init(_Xi18n_lock->lock); 6001ab64890Smrg xmutex_set_name(_Xi18n_lock->lock, "Xlib i18n"); 6011ab64890Smrg _XLockMutex_fn = _XLockMutex; 6021ab64890Smrg _XUnlockMutex_fn = _XUnlockMutex; 6031ab64890Smrg _XCreateMutex_fn = _XCreateMutex; 6041ab64890Smrg _XFreeMutex_fn = _XFreeMutex; 6051ab64890Smrg _XInitDisplayLock_fn = _XInitDisplayLock; 6061ab64890Smrg _XFreeDisplayLock_fn = _XFreeDisplayLock; 6071ab64890Smrg _Xthread_self_fn = _Xthread_self; 6081ab64890Smrg 6091ab64890Smrg#ifdef XTHREADS_WARN 6101ab64890Smrg#ifdef XTHREADS_DEBUG 6111ab64890Smrg setlinebuf(stdout); /* for debugging messages */ 6121ab64890Smrg#endif 6131ab64890Smrg#endif 6141ab64890Smrg 6151ab64890Smrg return 1; 6161ab64890Smrg} 6171ab64890Smrg 6181ab64890Smrg#else /* XTHREADS */ 6192e9c7c8cSmrgStatus XInitThreads(void) 6201ab64890Smrg{ 6211ab64890Smrg return 0; 6221ab64890Smrg} 6231ab64890Smrg#endif /* XTHREADS */ 624