| File: | src/locking.c |
| Location: | line 419, column 14 |
| Description: | Assigned value is garbage or undefined |
| 1 | /* | |||
| 2 | ||||
| 3 | Copyright 1992, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included in | |||
| 12 | all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| 18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| 20 | ||||
| 21 | Except as contained in this notice, the name of The Open Group shall not be | |||
| 22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
| 23 | in this Software without prior written authorization from The Open Group. | |||
| 24 | ||||
| 25 | */ | |||
| 26 | ||||
| 27 | /* | |||
| 28 | * Author: Stephen Gildea, MIT X Consortium | |||
| 29 | * | |||
| 30 | * locking.c - multi-thread locking routines implemented in C Threads | |||
| 31 | */ | |||
| 32 | ||||
| 33 | #ifdef HAVE_CONFIG_H1 | |||
| 34 | #include <config.h> | |||
| 35 | #endif | |||
| 36 | #include "Xlibint.h" | |||
| 37 | #undef _XLockMutex | |||
| 38 | #undef _XUnlockMutex | |||
| 39 | #undef _XCreateMutex | |||
| 40 | #undef _XFreeMutex | |||
| 41 | ||||
| 42 | #ifdef XTHREADS1 | |||
| 43 | ||||
| 44 | #ifdef __UNIXWARE__ | |||
| 45 | #include <dlfcn.h> | |||
| 46 | #endif | |||
| 47 | ||||
| 48 | #include "Xprivate.h" | |||
| 49 | #include "locking.h" | |||
| 50 | #ifdef XTHREADS_WARN | |||
| 51 | #include <stdio.h> /* for warn/debug stuff */ | |||
| 52 | #endif | |||
| 53 | ||||
| 54 | /* Additional arguments for source code location lock call was made from */ | |||
| 55 | #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE) | |||
| 56 | # define XTHREADS_FILE_LINE_ARGS \ | |||
| 57 | , \ | |||
| 58 | char* file, /* source file, from macro */ \ | |||
| 59 | int line | |||
| 60 | #else | |||
| 61 | # define XTHREADS_FILE_LINE_ARGS /* None */ | |||
| 62 | #endif | |||
| 63 | ||||
| 64 | ||||
| 65 | #define NUM_FREE_CVLS4 4 | |||
| 66 | ||||
| 67 | /* in lcWrap.c */ | |||
| 68 | extern LockInfoPtr _Xi18n_lock; | |||
| 69 | ||||
| 70 | #ifdef WIN32 | |||
| 71 | static DWORD _X_TlsIndex = (DWORD)-1; | |||
| 72 | ||||
| 73 | void _Xthread_init(void) | |||
| 74 | { | |||
| 75 | if (_X_TlsIndex == (DWORD)-1) | |||
| 76 | _X_TlsIndex = TlsAlloc(); | |||
| 77 | } | |||
| 78 | ||||
| 79 | struct _xthread_waiter * | |||
| 80 | _Xthread_waiter(void) | |||
| 81 | { | |||
| 82 | struct _xthread_waiter *me; | |||
| 83 | ||||
| 84 | if (!(me = TlsGetValue(_X_TlsIndex))) { | |||
| 85 | me = xmalloc(sizeof(struct _xthread_waiter))malloc(((sizeof(struct _xthread_waiter)) == 0 ? 1 : (sizeof(struct _xthread_waiter)))); | |||
| 86 | me->sem = CreateSemaphore(NULL((void*)0), 0, 1, NULL((void*)0)); | |||
| 87 | me->next = NULL((void*)0); | |||
| 88 | TlsSetValue(_X_TlsIndex, me); | |||
| 89 | } | |||
| 90 | return me; | |||
| 91 | } | |||
| 92 | #endif /* WIN32 */ | |||
| 93 | ||||
| 94 | static xthread_t _Xthread_self(void) | |||
| 95 | { | |||
| 96 | return xthread_selfpthread_self(); | |||
| 97 | } | |||
| 98 | ||||
| 99 | static LockInfoRec global_lock; | |||
| 100 | static LockInfoRec i18n_lock; | |||
| 101 | ||||
| 102 | static void _XLockMutex( | |||
| 103 | LockInfoPtr lip | |||
| 104 | XTHREADS_FILE_LINE_ARGS | |||
| 105 | ) | |||
| 106 | { | |||
| 107 | xmutex_lock(lip->lock)pthread_mutex_lock(lip->lock); | |||
| 108 | } | |||
| 109 | ||||
| 110 | static void _XUnlockMutex( | |||
| 111 | LockInfoPtr lip | |||
| 112 | XTHREADS_FILE_LINE_ARGS | |||
| 113 | ) | |||
| 114 | { | |||
| 115 | xmutex_unlock(lip->lock)pthread_mutex_unlock(lip->lock); | |||
| 116 | } | |||
| 117 | ||||
| 118 | static void _XCreateMutex( | |||
| 119 | LockInfoPtr lip) | |||
| 120 | { | |||
| 121 | lip->lock = xmutex_malloc()(xmutex_t)malloc(((sizeof(xmutex_rec)) == 0 ? 1 : (sizeof(xmutex_rec )))); | |||
| 122 | if (lip->lock) { | |||
| 123 | xmutex_init(lip->lock)pthread_mutex_init(lip->lock, ((void*)0)); | |||
| 124 | xmutex_set_name(lip->lock, "Xlib"); | |||
| 125 | } | |||
| 126 | } | |||
| 127 | ||||
| 128 | static void _XFreeMutex( | |||
| 129 | LockInfoPtr lip) | |||
| 130 | { | |||
| 131 | xmutex_clear(lip->lock)pthread_mutex_destroy(lip->lock); | |||
| 132 | xmutex_free(lip->lock)free(((char *)lip->lock)); | |||
| 133 | } | |||
| 134 | ||||
| 135 | #ifdef XTHREADS_WARN | |||
| 136 | static char *locking_file; | |||
| 137 | static int locking_line; | |||
| 138 | static xthread_t locking_thread; | |||
| 139 | static Boolint xlibint_unlock = False0; /* XlibInt.c may Unlock and re-Lock */ | |||
| 140 | ||||
| 141 | /* history that is useful to examine in a debugger */ | |||
| 142 | #define LOCK_HIST_SIZE 21 | |||
| 143 | ||||
| 144 | static struct { | |||
| 145 | Boolint lockp; /* True for lock, False for unlock */ | |||
| 146 | xthread_t thread; | |||
| 147 | char *file; | |||
| 148 | int line; | |||
| 149 | } locking_history[LOCK_HIST_SIZE]; | |||
| 150 | ||||
| 151 | int lock_hist_loc = 0; /* next slot to fill */ | |||
| 152 | ||||
| 153 | static void _XLockDisplayWarn( | |||
| 154 | Display *dpy, | |||
| 155 | char *file, /* source file, from macro */ | |||
| 156 | int line) | |||
| 157 | { | |||
| 158 | xthread_t self; | |||
| 159 | xthread_t old_locker; | |||
| 160 | ||||
| 161 | self = xthread_selfpthread_self(); | |||
| 162 | old_locker = locking_thread; | |||
| 163 | if (xthread_have_id(old_locker)old_locker) { | |||
| 164 | if (xthread_equal(old_locker, self)((old_locker) == (self))) | |||
| 165 | printf("Xlib ERROR: %s line %d thread %x: locking display already locked at %s line %d\n", | |||
| 166 | file, line, self, locking_file, locking_line); | |||
| 167 | #ifdef XTHREADS_DEBUG | |||
| 168 | else | |||
| 169 | printf("%s line %d: thread %x waiting on lock held by %s line %d thread %x\n", | |||
| 170 | file, line, self, | |||
| 171 | locking_file, locking_line, old_locker); | |||
| 172 | #endif /* XTHREADS_DEBUG */ | |||
| 173 | } | |||
| 174 | ||||
| 175 | xmutex_lock(dpy->lock->mutex)pthread_mutex_lock(dpy->lock->mutex); | |||
| 176 | ||||
| 177 | if (strcmp(file, "XlibInt.c") == 0) { | |||
| 178 | if (!xlibint_unlock) | |||
| 179 | printf("Xlib ERROR: XlibInt.c line %d thread %x locking display it did not unlock\n", | |||
| 180 | line, self); | |||
| 181 | xlibint_unlock = False0; | |||
| 182 | } | |||
| 183 | ||||
| 184 | #ifdef XTHREADS_DEBUG | |||
| 185 | /* if (old_locker && old_locker != self) */ | |||
| 186 | if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ | |||
| 187 | printf("%s line %d: thread %x got display lock\n", file, line, self); | |||
| 188 | #endif /* XTHREADS_DEBUG */ | |||
| 189 | ||||
| 190 | locking_thread = self; | |||
| 191 | if (strcmp(file, "XlibInt.c") != 0) { | |||
| 192 | locking_file = file; | |||
| 193 | locking_line = line; | |||
| 194 | } | |||
| 195 | locking_history[lock_hist_loc].file = file; | |||
| 196 | locking_history[lock_hist_loc].line = line; | |||
| 197 | locking_history[lock_hist_loc].thread = self; | |||
| 198 | locking_history[lock_hist_loc].lockp = True1; | |||
| 199 | lock_hist_loc++; | |||
| 200 | if (lock_hist_loc >= LOCK_HIST_SIZE) | |||
| 201 | lock_hist_loc = 0; | |||
| 202 | } | |||
| 203 | #endif /* XTHREADS_WARN */ | |||
| 204 | ||||
| 205 | static void _XUnlockDisplay( | |||
| 206 | Display *dpy | |||
| 207 | XTHREADS_FILE_LINE_ARGS | |||
| 208 | ) | |||
| 209 | { | |||
| 210 | #ifdef XTHREADS_WARN | |||
| 211 | xthread_t self = xthread_selfpthread_self(); | |||
| 212 | ||||
| 213 | #ifdef XTHREADS_DEBUG | |||
| 214 | if (strcmp("XClearArea.c", file) && strcmp("XDrSegs.c", file)) /* ico */ | |||
| 215 | printf("%s line %d: thread %x unlocking display\n", file, line, self); | |||
| 216 | #endif /* XTHREADS_DEBUG */ | |||
| 217 | ||||
| 218 | if (!xthread_have_id(locking_thread)locking_thread) | |||
| 219 | printf("Xlib ERROR: %s line %d thread %x: unlocking display that is not locked\n", | |||
| 220 | file, line, self); | |||
| 221 | else if (strcmp(file, "XlibInt.c") == 0) | |||
| 222 | xlibint_unlock = True1; | |||
| 223 | #ifdef XTHREADS_DEBUG | |||
| 224 | else if (strcmp(file, locking_file) != 0) | |||
| 225 | /* not always an error because locking_file is not per-thread */ | |||
| 226 | printf("%s line %d: unlocking display locked from %s line %d (probably okay)\n", | |||
| 227 | file, line, locking_file, locking_line); | |||
| 228 | #endif /* XTHREADS_DEBUG */ | |||
| 229 | xthread_clear_id(locking_thread)locking_thread = 0; | |||
| 230 | ||||
| 231 | locking_history[lock_hist_loc].file = file; | |||
| 232 | locking_history[lock_hist_loc].line = line; | |||
| 233 | locking_history[lock_hist_loc].thread = self; | |||
| 234 | locking_history[lock_hist_loc].lockp = False0; | |||
| 235 | lock_hist_loc++; | |||
| 236 | if (lock_hist_loc >= LOCK_HIST_SIZE) | |||
| 237 | lock_hist_loc = 0; | |||
| 238 | #endif /* XTHREADS_WARN */ | |||
| 239 | xmutex_unlock(dpy->lock->mutex)pthread_mutex_unlock(dpy->lock->mutex); | |||
| 240 | } | |||
| 241 | ||||
| 242 | ||||
| 243 | static struct _XCVList *_XCreateCVL( | |||
| 244 | Display *dpy) | |||
| 245 | { | |||
| 246 | struct _XCVList *cvl; | |||
| 247 | ||||
| 248 | if ((cvl = dpy->lock->free_cvls) != NULL((void*)0)) { | |||
| 249 | dpy->lock->free_cvls = cvl->next; | |||
| 250 | dpy->lock->num_free_cvls--; | |||
| 251 | } else { | |||
| 252 | cvl = Xmalloc(sizeof(struct _XCVList))malloc(((sizeof(struct _XCVList)) == 0 ? 1 : (sizeof(struct _XCVList )))); | |||
| 253 | if (!cvl) | |||
| 254 | return NULL((void*)0); | |||
| 255 | cvl->cv = xcondition_malloc()(xcondition_t)malloc(((sizeof(xcondition_rec)) == 0 ? 1 : (sizeof (xcondition_rec)))); | |||
| 256 | if (!cvl->cv) { | |||
| 257 | Xfree(cvl)free((cvl)); | |||
| 258 | return NULL((void*)0); | |||
| 259 | } | |||
| 260 | xcondition_init(cvl->cv)pthread_cond_init(cvl->cv, ((void*)0)); | |||
| 261 | xcondition_set_name(cvl->cv, "Xlib read queue"); | |||
| 262 | } | |||
| 263 | cvl->next = NULL((void*)0); | |||
| 264 | return cvl; | |||
| 265 | } | |||
| 266 | ||||
| 267 | /* Put ourselves on the queue to read the connection. | |||
| 268 | Allocates and returns a queue element. */ | |||
| 269 | ||||
| 270 | static struct _XCVList * | |||
| 271 | _XPushReader( | |||
| 272 | Display *dpy, | |||
| 273 | struct _XCVList ***tail) | |||
| 274 | { | |||
| 275 | struct _XCVList *cvl; | |||
| 276 | ||||
| 277 | cvl = _XCreateCVL(dpy); | |||
| 278 | #ifdef XTHREADS_DEBUG | |||
| 279 | printf("_XPushReader called in thread %x, pushing %x\n", | |||
| 280 | xthread_selfpthread_self(), cvl); | |||
| 281 | #endif | |||
| 282 | **tail = cvl; | |||
| 283 | *tail = &cvl->next; | |||
| 284 | return cvl; | |||
| 285 | } | |||
| 286 | ||||
| 287 | /* signal the next thread waiting to read the connection */ | |||
| 288 | ||||
| 289 | static void _XPopReader( | |||
| 290 | Display *dpy, | |||
| 291 | struct _XCVList **list, | |||
| 292 | struct _XCVList ***tail) | |||
| 293 | { | |||
| 294 | register struct _XCVList *front = *list; | |||
| 295 | ||||
| 296 | #ifdef XTHREADS_DEBUG | |||
| 297 | printf("_XPopReader called in thread %x, popping %x\n", | |||
| 298 | xthread_selfpthread_self(), front); | |||
| 299 | #endif | |||
| 300 | ||||
| 301 | if (dpy->flags & XlibDisplayProcConni(1L << 4)) | |||
| 302 | /* we never added ourself in the first place */ | |||
| 303 | return; | |||
| 304 | ||||
| 305 | if (front) { /* check "front" for paranoia */ | |||
| 306 | *list = front->next; | |||
| 307 | if (*tail == &front->next) /* did we free the last elt? */ | |||
| 308 | *tail = list; | |||
| 309 | if (dpy->lock->num_free_cvls < NUM_FREE_CVLS4) { | |||
| 310 | front->next = dpy->lock->free_cvls; | |||
| 311 | dpy->lock->free_cvls = front; | |||
| 312 | dpy->lock->num_free_cvls++; | |||
| 313 | } else { | |||
| 314 | xcondition_clear(front->cv)pthread_cond_destroy(front->cv); | |||
| 315 | Xfree(front->cv)free((front->cv)); | |||
| 316 | Xfree(front)free((front)); | |||
| 317 | } | |||
| 318 | } | |||
| 319 | ||||
| 320 | /* signal new front after it is in place */ | |||
| 321 | if ((dpy->lock->reply_first = (dpy->lock->reply_awaiters != NULL((void*)0)))) { | |||
| 322 | ConditionSignal(dpy, dpy->lock->reply_awaiters->cv)if ((dpy)->lock) (*(dpy)->lock->condition_signal)(dpy ->lock->reply_awaiters->cv); | |||
| 323 | } else if (dpy->lock->event_awaiters) { | |||
| 324 | ConditionSignal(dpy, dpy->lock->event_awaiters->cv)if ((dpy)->lock) (*(dpy)->lock->condition_signal)(dpy ->lock->event_awaiters->cv); | |||
| 325 | } | |||
| 326 | } | |||
| 327 | ||||
| 328 | static void _XConditionWait( | |||
| 329 | xcondition_t cv, | |||
| 330 | xmutex_t mutex | |||
| 331 | XTHREADS_FILE_LINE_ARGS | |||
| 332 | ) | |||
| 333 | { | |||
| 334 | #ifdef XTHREADS_WARN | |||
| 335 | xthread_t self = xthread_selfpthread_self(); | |||
| 336 | char *old_file = locking_file; | |||
| 337 | int old_line = locking_line; | |||
| 338 | ||||
| 339 | #ifdef XTHREADS_DEBUG | |||
| 340 | printf("line %d thread %x in condition wait\n", line, self); | |||
| 341 | #endif | |||
| 342 | xthread_clear_id(locking_thread)locking_thread = 0; | |||
| 343 | ||||
| 344 | locking_history[lock_hist_loc].file = file; | |||
| 345 | locking_history[lock_hist_loc].line = line; | |||
| 346 | locking_history[lock_hist_loc].thread = self; | |||
| 347 | locking_history[lock_hist_loc].lockp = False0; | |||
| 348 | lock_hist_loc++; | |||
| 349 | if (lock_hist_loc >= LOCK_HIST_SIZE) | |||
| 350 | lock_hist_loc = 0; | |||
| 351 | #endif /* XTHREADS_WARN */ | |||
| 352 | ||||
| 353 | xcondition_wait(cv, mutex)pthread_cond_wait(cv,mutex); | |||
| 354 | ||||
| 355 | #ifdef XTHREADS_WARN | |||
| 356 | locking_thread = self; | |||
| 357 | locking_file = old_file; | |||
| 358 | locking_line = old_line; | |||
| 359 | ||||
| 360 | locking_history[lock_hist_loc].file = file; | |||
| 361 | locking_history[lock_hist_loc].line = line; | |||
| 362 | locking_history[lock_hist_loc].thread = self; | |||
| 363 | locking_history[lock_hist_loc].lockp = True1; | |||
| 364 | lock_hist_loc++; | |||
| 365 | if (lock_hist_loc >= LOCK_HIST_SIZE) | |||
| 366 | lock_hist_loc = 0; | |||
| 367 | #ifdef XTHREADS_DEBUG | |||
| 368 | printf("line %d thread %x was signaled\n", line, self); | |||
| 369 | #endif /* XTHREADS_DEBUG */ | |||
| 370 | #endif /* XTHREADS_WARN */ | |||
| 371 | } | |||
| 372 | ||||
| 373 | static void _XConditionSignal( | |||
| 374 | xcondition_t cv | |||
| 375 | XTHREADS_FILE_LINE_ARGS | |||
| 376 | ) | |||
| 377 | { | |||
| 378 | #ifdef XTHREADS_WARN | |||
| 379 | #ifdef XTHREADS_DEBUG | |||
| 380 | printf("line %d thread %x is signalling\n", line, xthread_selfpthread_self()); | |||
| 381 | #endif | |||
| 382 | #endif | |||
| 383 | xcondition_signal(cv)pthread_cond_signal(cv); | |||
| 384 | } | |||
| 385 | ||||
| 386 | ||||
| 387 | static void _XConditionBroadcast( | |||
| 388 | xcondition_t cv | |||
| 389 | XTHREADS_FILE_LINE_ARGS | |||
| 390 | ) | |||
| 391 | { | |||
| 392 | #ifdef XTHREADS_WARN | |||
| 393 | #ifdef XTHREADS_DEBUG | |||
| 394 | printf("line %d thread %x is broadcasting\n", line, xthread_selfpthread_self()); | |||
| 395 | #endif | |||
| 396 | #endif | |||
| 397 | xcondition_broadcast(cv)pthread_cond_broadcast(cv); | |||
| 398 | } | |||
| 399 | ||||
| 400 | ||||
| 401 | static void _XFreeDisplayLock( | |||
| 402 | Display *dpy) | |||
| 403 | { | |||
| 404 | struct _XCVList *cvl; | |||
| 405 | ||||
| 406 | if (dpy->lock != NULL((void*)0)) { | |||
| 407 | if (dpy->lock->mutex != NULL((void*)0)) { | |||
| 408 | xmutex_clear(dpy->lock->mutex)pthread_mutex_destroy(dpy->lock->mutex); | |||
| 409 | xmutex_free(dpy->lock->mutex)free(((char *)dpy->lock->mutex)); | |||
| 410 | } | |||
| 411 | if (dpy->lock->cv != NULL((void*)0)) { | |||
| 412 | xcondition_clear(dpy->lock->cv)pthread_cond_destroy(dpy->lock->cv); | |||
| 413 | xcondition_free(dpy->lock->cv)free(((char *)dpy->lock->cv)); | |||
| 414 | } | |||
| 415 | if (dpy->lock->writers != NULL((void*)0)) { | |||
| 416 | xcondition_clear(dpy->lock->writers)pthread_cond_destroy(dpy->lock->writers); | |||
| 417 | xcondition_free(dpy->lock->writers)free(((char *)dpy->lock->writers)); | |||
| 418 | } | |||
| 419 | while ((cvl = dpy->lock->free_cvls)) { | |||
| ||||
| 420 | dpy->lock->free_cvls = cvl->next; | |||
| 421 | xcondition_clear(cvl->cv)pthread_cond_destroy(cvl->cv); | |||
| 422 | Xfree(cvl->cv)free((cvl->cv)); | |||
| 423 | Xfree(cvl)free((cvl)); | |||
| 424 | } | |||
| 425 | Xfree(dpy->lock)free((dpy->lock)); | |||
| 426 | dpy->lock = NULL((void*)0); | |||
| 427 | } | |||
| 428 | if (dpy->lock_fns != NULL((void*)0)) { | |||
| 429 | Xfree(dpy->lock_fns)free((dpy->lock_fns)); | |||
| 430 | dpy->lock_fns = NULL((void*)0); | |||
| 431 | } | |||
| 432 | } | |||
| 433 | ||||
| 434 | /* | |||
| 435 | * wait for thread with user-level display lock to release it. | |||
| 436 | */ | |||
| 437 | ||||
| 438 | static void _XDisplayLockWait( | |||
| 439 | Display *dpy) | |||
| 440 | { | |||
| 441 | xthread_t self; | |||
| 442 | ||||
| 443 | while (dpy->lock->locking_level > 0) { | |||
| 444 | self = xthread_selfpthread_self(); | |||
| 445 | if (xthread_equal(dpy->lock->locking_thread, self)((dpy->lock->locking_thread) == (self))) | |||
| 446 | break; | |||
| 447 | ConditionWait(dpy, dpy->lock->cv)if ((dpy)->lock) (*(dpy)->lock->condition_wait)(dpy-> lock->cv, (dpy)->lock->mutex); | |||
| 448 | } | |||
| 449 | } | |||
| 450 | ||||
| 451 | static void _XLockDisplay( | |||
| 452 | Display *dpy | |||
| 453 | XTHREADS_FILE_LINE_ARGS | |||
| 454 | ) | |||
| 455 | { | |||
| 456 | #ifdef XTHREADS_WARN | |||
| 457 | _XLockDisplayWarn(dpy, file, line); | |||
| 458 | #else | |||
| 459 | xmutex_lock(dpy->lock->mutex)pthread_mutex_lock(dpy->lock->mutex); | |||
| 460 | #endif | |||
| 461 | if (dpy->lock->locking_level > 0) | |||
| 462 | _XDisplayLockWait(dpy); | |||
| 463 | _XIDHandler(dpy); | |||
| 464 | _XSeqSyncFunction(dpy); | |||
| 465 | } | |||
| 466 | ||||
| 467 | /* | |||
| 468 | * _XReply is allowed to exit from select/poll and clean up even if a | |||
| 469 | * user-level lock is in force, so it uses this instead of _XFancyLockDisplay. | |||
| 470 | */ | |||
| 471 | static void _XInternalLockDisplay( | |||
| 472 | Display *dpy, | |||
| 473 | Boolint wskip | |||
| 474 | XTHREADS_FILE_LINE_ARGS | |||
| 475 | ) | |||
| 476 | { | |||
| 477 | #ifdef XTHREADS_WARN | |||
| 478 | _XLockDisplayWarn(dpy, file, line); | |||
| 479 | #else | |||
| 480 | xmutex_lock(dpy->lock->mutex)pthread_mutex_lock(dpy->lock->mutex); | |||
| 481 | #endif | |||
| 482 | if (!wskip && dpy->lock->locking_level > 0) | |||
| 483 | _XDisplayLockWait(dpy); | |||
| 484 | } | |||
| 485 | ||||
| 486 | static void _XUserLockDisplay( | |||
| 487 | register Display* dpy) | |||
| 488 | { | |||
| 489 | _XDisplayLockWait(dpy); | |||
| 490 | ||||
| 491 | if (++dpy->lock->locking_level == 1) { | |||
| 492 | dpy->lock->lock_wait = _XDisplayLockWait; | |||
| 493 | dpy->lock->locking_thread = xthread_selfpthread_self(); | |||
| 494 | } | |||
| 495 | } | |||
| 496 | ||||
| 497 | static | |||
| 498 | void _XUserUnlockDisplay( | |||
| 499 | register Display* dpy) | |||
| 500 | { | |||
| 501 | if (dpy->lock->locking_level > 0 && --dpy->lock->locking_level == 0) { | |||
| 502 | /* signal other threads that might be waiting in XLockDisplay */ | |||
| 503 | ConditionBroadcast(dpy, dpy->lock->cv)if ((dpy)->lock) (*(dpy)->lock->condition_broadcast) (dpy->lock->cv); | |||
| 504 | dpy->lock->lock_wait = NULL((void*)0); | |||
| 505 | xthread_clear_id(dpy->lock->locking_thread)dpy->lock->locking_thread = 0; | |||
| 506 | } | |||
| 507 | } | |||
| 508 | ||||
| 509 | /* returns 0 if initialized ok, -1 if unable to allocate | |||
| 510 | a mutex or other memory */ | |||
| 511 | ||||
| 512 | static int _XInitDisplayLock( | |||
| 513 | Display *dpy) | |||
| 514 | { | |||
| 515 | dpy->lock_fns = Xmalloc(sizeof(struct _XLockPtrs))malloc(((sizeof(struct _XLockPtrs)) == 0 ? 1 : (sizeof(struct _XLockPtrs)))); | |||
| 516 | if (dpy->lock_fns == NULL((void*)0)) | |||
| ||||
| 517 | return -1; | |||
| 518 | dpy->lock = Xmalloc(sizeof(struct _XLockInfo))malloc(((sizeof(struct _XLockInfo)) == 0 ? 1 : (sizeof(struct _XLockInfo)))); | |||
| 519 | if (dpy->lock == NULL((void*)0)) { | |||
| 520 | _XFreeDisplayLock(dpy); | |||
| 521 | return -1; | |||
| 522 | } | |||
| 523 | dpy->lock->cv = xcondition_malloc()(xcondition_t)malloc(((sizeof(xcondition_rec)) == 0 ? 1 : (sizeof (xcondition_rec)))); | |||
| 524 | dpy->lock->mutex = xmutex_malloc()(xmutex_t)malloc(((sizeof(xmutex_rec)) == 0 ? 1 : (sizeof(xmutex_rec )))); | |||
| 525 | dpy->lock->writers = xcondition_malloc()(xcondition_t)malloc(((sizeof(xcondition_rec)) == 0 ? 1 : (sizeof (xcondition_rec)))); | |||
| 526 | if (!dpy->lock->cv || !dpy->lock->mutex || !dpy->lock->writers) { | |||
| 527 | _XFreeDisplayLock(dpy); | |||
| 528 | return -1; | |||
| 529 | } | |||
| 530 | ||||
| 531 | dpy->lock->reply_bytes_left = 0; | |||
| 532 | dpy->lock->reply_was_read = False0; | |||
| 533 | dpy->lock->reply_awaiters = NULL((void*)0); | |||
| 534 | dpy->lock->reply_awaiters_tail = &dpy->lock->reply_awaiters; | |||
| 535 | dpy->lock->event_awaiters = NULL((void*)0); | |||
| 536 | dpy->lock->event_awaiters_tail = &dpy->lock->event_awaiters; | |||
| 537 | dpy->lock->reply_first = False0; | |||
| 538 | dpy->lock->locking_level = 0; | |||
| 539 | dpy->lock->num_free_cvls = 0; | |||
| 540 | dpy->lock->free_cvls = NULL((void*)0); | |||
| 541 | xthread_clear_id(dpy->lock->locking_thread)dpy->lock->locking_thread = 0; | |||
| 542 | xthread_clear_id(dpy->lock->reading_thread)dpy->lock->reading_thread = 0; | |||
| 543 | xthread_clear_id(dpy->lock->conni_thread)dpy->lock->conni_thread = 0; | |||
| 544 | xmutex_init(dpy->lock->mutex)pthread_mutex_init(dpy->lock->mutex, ((void*)0)); | |||
| 545 | xmutex_set_name(dpy->lock->mutex, "Xlib Display"); | |||
| 546 | xcondition_init(dpy->lock->cv)pthread_cond_init(dpy->lock->cv, ((void*)0)); | |||
| 547 | xcondition_set_name(dpy->lock->cv, "XLockDisplay"); | |||
| 548 | xcondition_init(dpy->lock->writers)pthread_cond_init(dpy->lock->writers, ((void*)0)); | |||
| 549 | xcondition_set_name(dpy->lock->writers, "Xlib wait for writable"); | |||
| 550 | dpy->lock_fns->lock_display = _XLockDisplay; | |||
| 551 | dpy->lock->internal_lock_display = _XInternalLockDisplay; | |||
| 552 | dpy->lock_fns->unlock_display = _XUnlockDisplay; | |||
| 553 | dpy->lock->user_lock_display = _XUserLockDisplay; | |||
| 554 | dpy->lock->user_unlock_display = _XUserUnlockDisplay; | |||
| 555 | dpy->lock->pop_reader = _XPopReader; | |||
| 556 | dpy->lock->push_reader = _XPushReader; | |||
| 557 | dpy->lock->condition_wait = _XConditionWait; | |||
| 558 | dpy->lock->condition_signal = _XConditionSignal; | |||
| 559 | dpy->lock->condition_broadcast = _XConditionBroadcast; | |||
| 560 | dpy->lock->create_cvl = _XCreateCVL; | |||
| 561 | dpy->lock->lock_wait = NULL((void*)0); /* filled in by XLockDisplay() */ | |||
| 562 | ||||
| 563 | return 0; | |||
| 564 | } | |||
| 565 | ||||
| 566 | #ifdef __UNIXWARE__ | |||
| 567 | xthread_t __x11_thr_self() { return 0; } | |||
| 568 | xthread_t (*_x11_thr_self)() = __x11_thr_self; | |||
| 569 | #endif | |||
| 570 | ||||
| 571 | ||||
| 572 | Statusint XInitThreads(void) | |||
| 573 | { | |||
| 574 | if (_Xglobal_lock) | |||
| 575 | return 1; | |||
| 576 | #ifdef __UNIXWARE__ | |||
| 577 | else { | |||
| 578 | void *dl_handle = dlopen(NULL((void*)0), RTLD_LAZY); | |||
| 579 | if (!dl_handle || | |||
| 580 | ((_x11_thr_self = (xthread_t(*)())dlsym(dl_handle,"thr_self")) == 0)) { | |||
| 581 | _x11_thr_self = __x11_thr_self; | |||
| 582 | (void) fprintf (stderr, | |||
| 583 | "XInitThreads called, but no libthread in the calling program!\n" ); | |||
| 584 | } | |||
| 585 | } | |||
| 586 | #endif /* __UNIXWARE__ */ | |||
| 587 | #ifdef xthread_init | |||
| 588 | xthread_init(); /* return value? */ | |||
| 589 | #endif | |||
| 590 | if (!(global_lock.lock = xmutex_malloc()(xmutex_t)malloc(((sizeof(xmutex_rec)) == 0 ? 1 : (sizeof(xmutex_rec )))))) | |||
| 591 | return 0; | |||
| 592 | if (!(i18n_lock.lock = xmutex_malloc()(xmutex_t)malloc(((sizeof(xmutex_rec)) == 0 ? 1 : (sizeof(xmutex_rec )))))) { | |||
| 593 | xmutex_free(global_lock.lock)free(((char *)global_lock.lock)); | |||
| 594 | global_lock.lock = NULL((void*)0); | |||
| 595 | return 0; | |||
| 596 | } | |||
| 597 | _Xglobal_lock = &global_lock; | |||
| 598 | xmutex_init(_Xglobal_lock->lock)pthread_mutex_init(_Xglobal_lock->lock, ((void*)0)); | |||
| 599 | xmutex_set_name(_Xglobal_lock->lock, "Xlib global"); | |||
| 600 | _Xi18n_lock = &i18n_lock; | |||
| 601 | xmutex_init(_Xi18n_lock->lock)pthread_mutex_init(_Xi18n_lock->lock, ((void*)0)); | |||
| 602 | xmutex_set_name(_Xi18n_lock->lock, "Xlib i18n"); | |||
| 603 | _XLockMutex_fn = _XLockMutex; | |||
| 604 | _XUnlockMutex_fn = _XUnlockMutex; | |||
| 605 | _XCreateMutex_fn = _XCreateMutex; | |||
| 606 | _XFreeMutex_fn = _XFreeMutex; | |||
| 607 | _XInitDisplayLock_fn = _XInitDisplayLock; | |||
| 608 | _XFreeDisplayLock_fn = _XFreeDisplayLock; | |||
| 609 | _Xthread_self_fn = _Xthread_self; | |||
| 610 | ||||
| 611 | #ifdef XTHREADS_WARN | |||
| 612 | #ifdef XTHREADS_DEBUG | |||
| 613 | setlinebuf(stdout); /* for debugging messages */ | |||
| 614 | #endif | |||
| 615 | #endif | |||
| 616 | ||||
| 617 | return 1; | |||
| 618 | } | |||
| 619 | ||||
| 620 | #else /* XTHREADS */ | |||
| 621 | Statusint XInitThreads(void) | |||
| 622 | { | |||
| 623 | return 0; | |||
| 624 | } | |||
| 625 | #endif /* XTHREADS */ |