Threads.c revision 444c061a
1444c061aSmrg/* $Xorg: Threads.c,v 1.4 2001/02/09 02:03:59 xorgcvs Exp $ */ 2444c061aSmrg 3444c061aSmrg/************************************************************ 4444c061aSmrgCopyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 5444c061aSmrg 6444c061aSmrg All Rights Reserved 7444c061aSmrg 8444c061aSmrgPermission to use, copy, modify, and distribute this 9444c061aSmrgsoftware and its documentation for any purpose and without 10444c061aSmrgfee is hereby granted, provided that the above copyright no- 11444c061aSmrgtice appear in all copies and that both that copyright no- 12444c061aSmrgtice and this permission notice appear in supporting docu- 13444c061aSmrgmentation, and that the name Sun not be used in advertising 14444c061aSmrgor publicity pertaining to distribution of the software 15444c061aSmrgwithout specific prior written permission. Sun makes no 16444c061aSmrgrepresentations about the suitability of this software for 17444c061aSmrgany purpose. It is provided "as is" without any express or 18444c061aSmrgimplied warranty. 19444c061aSmrg 20444c061aSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 21444c061aSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 22444c061aSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 23444c061aSmrgABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 24444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 25444c061aSmrgPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26444c061aSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 27444c061aSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 28444c061aSmrg 29444c061aSmrg********************************************************/ 30444c061aSmrg 31444c061aSmrg/* 32444c061aSmrg 33444c061aSmrgCopyright 1994, 1998 The Open Group 34444c061aSmrg 35444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 36444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 37444c061aSmrgthe above copyright notice appear in all copies and that both that 38444c061aSmrgcopyright notice and this permission notice appear in supporting 39444c061aSmrgdocumentation. 40444c061aSmrg 41444c061aSmrgThe above copyright notice and this permission notice shall be included in 42444c061aSmrgall copies or substantial portions of the Software. 43444c061aSmrg 44444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 48444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 49444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 50444c061aSmrg 51444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 52444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 53444c061aSmrgin this Software without prior written authorization from The Open Group. 54444c061aSmrg 55444c061aSmrg*/ 56444c061aSmrg/* $XFree86: xc/lib/Xt/Threads.c,v 3.6 2001/12/14 19:56:31 dawes Exp $ */ 57444c061aSmrg 58444c061aSmrg#ifdef HAVE_CONFIG_H 59444c061aSmrg#include <config.h> 60444c061aSmrg#endif 61444c061aSmrg#include "IntrinsicI.h" 62444c061aSmrg 63444c061aSmrg#ifdef XTHREADS 64444c061aSmrg 65444c061aSmrg#define xmalloc __XtMalloc 66444c061aSmrg#define xfree XtFree 67444c061aSmrg#include <X11/Xthreads.h> 68444c061aSmrg 69444c061aSmrg#ifndef NDEBUG 70444c061aSmrg#define NDEBUG 71444c061aSmrg#endif 72444c061aSmrg#include <assert.h> 73444c061aSmrg#include <stdio.h> 74444c061aSmrg 75444c061aSmrgtypedef struct _ThreadStack { 76444c061aSmrg unsigned int size; 77444c061aSmrg int sp; 78444c061aSmrg struct _Tstack { 79444c061aSmrg xthread_t t; 80444c061aSmrg xcondition_t c; 81444c061aSmrg } *st; 82444c061aSmrg} ThreadStack; 83444c061aSmrg 84444c061aSmrgtypedef struct _LockRec { 85444c061aSmrg xmutex_t mutex; 86444c061aSmrg int level; 87444c061aSmrg ThreadStack stack; 88444c061aSmrg#ifndef _XMUTEX_NESTS 89444c061aSmrg xthread_t holder; 90444c061aSmrg xcondition_t cond; 91444c061aSmrg#endif 92444c061aSmrg} LockRec; 93444c061aSmrg 94444c061aSmrg 95444c061aSmrg#define STACK_INCR 16 96444c061aSmrg 97444c061aSmrgstatic LockPtr process_lock = NULL; 98444c061aSmrg 99444c061aSmrgstatic void 100444c061aSmrgInitProcessLock(void) 101444c061aSmrg{ 102444c061aSmrg if(!process_lock) { 103444c061aSmrg process_lock = XtNew(LockRec); 104444c061aSmrg process_lock->mutex = xmutex_malloc(); 105444c061aSmrg xmutex_init(process_lock->mutex); 106444c061aSmrg process_lock->level = 0; 107444c061aSmrg#ifndef _XMUTEX_NESTS 108444c061aSmrg process_lock->cond = xcondition_malloc(); 109444c061aSmrg xcondition_init(process_lock->cond); 110444c061aSmrg xthread_clear_id(process_lock->holder); 111444c061aSmrg#endif 112444c061aSmrg } 113444c061aSmrg} 114444c061aSmrg 115444c061aSmrgstatic void 116444c061aSmrgProcessLock(void) 117444c061aSmrg{ 118444c061aSmrg#ifdef _XMUTEX_NESTS 119444c061aSmrg xmutex_lock(process_lock->mutex); 120444c061aSmrg process_lock->level++; 121444c061aSmrg#else 122444c061aSmrg xthread_t this_thread = xthread_self(); 123444c061aSmrg 124444c061aSmrg xmutex_lock(process_lock->mutex); 125444c061aSmrg 126444c061aSmrg if (!xthread_have_id(process_lock->holder)) { 127444c061aSmrg process_lock->holder = this_thread; 128444c061aSmrg xmutex_unlock(process_lock->mutex); 129444c061aSmrg return; 130444c061aSmrg } 131444c061aSmrg 132444c061aSmrg if (xthread_equal(process_lock->holder,this_thread)) { 133444c061aSmrg process_lock->level++; 134444c061aSmrg xmutex_unlock(process_lock->mutex); 135444c061aSmrg return; 136444c061aSmrg } 137444c061aSmrg 138444c061aSmrg while(xthread_have_id(process_lock->holder)) 139444c061aSmrg xcondition_wait(process_lock->cond, process_lock->mutex); 140444c061aSmrg 141444c061aSmrg process_lock->holder = this_thread; 142444c061aSmrg assert(xthread_equal(process_lock->holder, this_thread)); 143444c061aSmrg xmutex_unlock(process_lock->mutex); 144444c061aSmrg#endif 145444c061aSmrg} 146444c061aSmrg 147444c061aSmrgstatic void 148444c061aSmrgProcessUnlock(void) 149444c061aSmrg{ 150444c061aSmrg#ifdef _XMUTEX_NESTS 151444c061aSmrg process_lock->level--; 152444c061aSmrg xmutex_unlock(process_lock->mutex); 153444c061aSmrg#else 154444c061aSmrg xmutex_lock(process_lock->mutex); 155444c061aSmrg assert(xthread_equal(process_lock->holder, xthread_self())); 156444c061aSmrg if (process_lock->level != 0) { 157444c061aSmrg process_lock->level--; 158444c061aSmrg xmutex_unlock(process_lock->mutex); 159444c061aSmrg return; 160444c061aSmrg } 161444c061aSmrg 162444c061aSmrg xthread_clear_id(process_lock->holder); 163444c061aSmrg xcondition_signal(process_lock->cond); 164444c061aSmrg 165444c061aSmrg xmutex_unlock(process_lock->mutex); 166444c061aSmrg#endif 167444c061aSmrg} 168444c061aSmrg 169444c061aSmrg 170444c061aSmrgstatic void 171444c061aSmrgAppLock(XtAppContext app) 172444c061aSmrg{ 173444c061aSmrg LockPtr app_lock = app->lock_info; 174444c061aSmrg#ifdef _XMUTEX_NESTS 175444c061aSmrg xmutex_lock(app_lock->mutex); 176444c061aSmrg app_lock->level++; 177444c061aSmrg#else 178444c061aSmrg xthread_t self = xthread_self(); 179444c061aSmrg xmutex_lock(app_lock->mutex); 180444c061aSmrg if (!xthread_have_id(app_lock->holder)) { 181444c061aSmrg app_lock->holder = self; 182444c061aSmrg assert(xthread_equal(app_lock->holder, self)); 183444c061aSmrg xmutex_unlock(app_lock->mutex); 184444c061aSmrg return; 185444c061aSmrg } 186444c061aSmrg if (xthread_equal(app_lock->holder, self)) { 187444c061aSmrg app_lock->level++; 188444c061aSmrg xmutex_unlock(app_lock->mutex); 189444c061aSmrg return; 190444c061aSmrg } 191444c061aSmrg while(xthread_have_id(app_lock->holder)) { 192444c061aSmrg xcondition_wait(app_lock->cond, app_lock->mutex); 193444c061aSmrg } 194444c061aSmrg app_lock->holder = self; 195444c061aSmrg assert(xthread_equal(app_lock->holder, self)); 196444c061aSmrg xmutex_unlock(app_lock->mutex); 197444c061aSmrg#endif 198444c061aSmrg} 199444c061aSmrg 200444c061aSmrgstatic void 201444c061aSmrgAppUnlock(XtAppContext app) 202444c061aSmrg{ 203444c061aSmrg LockPtr app_lock = app->lock_info; 204444c061aSmrg#ifdef _XMUTEX_NESTS 205444c061aSmrg app_lock->level--; 206444c061aSmrg xmutex_unlock(app_lock->mutex); 207444c061aSmrg#else 208444c061aSmrg xthread_t self; 209444c061aSmrg 210444c061aSmrg self = xthread_self(); 211444c061aSmrg xmutex_lock(app_lock->mutex); 212444c061aSmrg assert(xthread_equal(app_lock->holder, self)); 213444c061aSmrg if (app_lock->level != 0) { 214444c061aSmrg app_lock->level--; 215444c061aSmrg xmutex_unlock(app_lock->mutex); 216444c061aSmrg return; 217444c061aSmrg } 218444c061aSmrg xthread_clear_id(app_lock->holder); 219444c061aSmrg xcondition_signal(app_lock->cond); 220444c061aSmrg xmutex_unlock(app_lock->mutex); 221444c061aSmrg#endif 222444c061aSmrg} 223444c061aSmrg 224444c061aSmrgstatic void 225444c061aSmrgYieldAppLock( 226444c061aSmrg XtAppContext app, 227444c061aSmrg Boolean* push_thread, 228444c061aSmrg Boolean* pushed_thread, 229444c061aSmrg int* level) 230444c061aSmrg{ 231444c061aSmrg LockPtr app_lock = app->lock_info; 232444c061aSmrg xthread_t self = xthread_self(); 233444c061aSmrg#ifndef _XMUTEX_NESTS 234444c061aSmrg xmutex_lock(app_lock->mutex); 235444c061aSmrg assert(xthread_equal(app_lock->holder, self)); 236444c061aSmrg#endif 237444c061aSmrg *level = app_lock->level; 238444c061aSmrg if (*push_thread) { 239444c061aSmrg *push_thread = FALSE; 240444c061aSmrg *pushed_thread = TRUE; 241444c061aSmrg 242444c061aSmrg if(app_lock->stack.sp == (int)app_lock->stack.size - 1) { 243444c061aSmrg unsigned ii; 244444c061aSmrg app_lock->stack.st = (struct _Tstack *) 245444c061aSmrg XtRealloc ((char *)app_lock->stack.st, 246444c061aSmrg (app_lock->stack.size + STACK_INCR) * sizeof (struct _Tstack)); 247444c061aSmrg ii = app_lock->stack.size; 248444c061aSmrg app_lock->stack.size += STACK_INCR; 249444c061aSmrg for ( ; ii < app_lock->stack.size; ii++) { 250444c061aSmrg app_lock->stack.st[ii].c = xcondition_malloc(); 251444c061aSmrg xcondition_init(app_lock->stack.st[ii].c); 252444c061aSmrg } 253444c061aSmrg } 254444c061aSmrg app_lock->stack.st[++(app_lock->stack.sp)].t = self; 255444c061aSmrg } 256444c061aSmrg#ifdef _XMUTEX_NESTS 257444c061aSmrg while (app_lock->level > 0) { 258444c061aSmrg app_lock->level--; 259444c061aSmrg xmutex_unlock(app_lock->mutex); 260444c061aSmrg } 261444c061aSmrg#else 262444c061aSmrg xcondition_signal(app_lock->cond); 263444c061aSmrg app_lock->level = 0; 264444c061aSmrg xthread_clear_id(app_lock->holder); 265444c061aSmrg xmutex_unlock(app_lock->mutex); 266444c061aSmrg#endif 267444c061aSmrg} 268444c061aSmrg 269444c061aSmrgstatic void 270444c061aSmrgRestoreAppLock( 271444c061aSmrg XtAppContext app, 272444c061aSmrg int level, 273444c061aSmrg Boolean* pushed_thread) 274444c061aSmrg{ 275444c061aSmrg LockPtr app_lock = app->lock_info; 276444c061aSmrg xthread_t self = xthread_self(); 277444c061aSmrg xmutex_lock(app_lock->mutex); 278444c061aSmrg#ifdef _XMUTEX_NESTS 279444c061aSmrg app_lock->level++; 280444c061aSmrg#else 281444c061aSmrg while(xthread_have_id(app_lock->holder)) { 282444c061aSmrg xcondition_wait(app_lock->cond, app_lock->mutex); 283444c061aSmrg } 284444c061aSmrg#endif 285444c061aSmrg if (!xthread_equal(app_lock->stack.st[app_lock->stack.sp].t, self)) { 286444c061aSmrg int ii; 287444c061aSmrg for (ii = app_lock->stack.sp - 1; ii >= 0; ii--) { 288444c061aSmrg if (xthread_equal(app_lock->stack.st[ii].t, self)) { 289444c061aSmrg xcondition_wait(app_lock->stack.st[ii].c, app_lock->mutex); 290444c061aSmrg break; 291444c061aSmrg } 292444c061aSmrg } 293444c061aSmrg#ifndef _XMUTEX_NESTS 294444c061aSmrg while(xthread_have_id(app_lock->holder)) { 295444c061aSmrg xcondition_wait(app_lock->cond, app_lock->mutex); 296444c061aSmrg } 297444c061aSmrg#endif 298444c061aSmrg } 299444c061aSmrg#ifdef _XMUTEX_NESTS 300444c061aSmrg while (app_lock->level < level) { 301444c061aSmrg xmutex_lock(app_lock->mutex); 302444c061aSmrg app_lock->level++; 303444c061aSmrg } 304444c061aSmrg#else 305444c061aSmrg app_lock->holder = self; 306444c061aSmrg app_lock->level = level; 307444c061aSmrg assert(xthread_equal(app_lock->holder, self)); 308444c061aSmrg#endif 309444c061aSmrg if (*pushed_thread) { 310444c061aSmrg *pushed_thread = FALSE; 311444c061aSmrg (app_lock->stack.sp)--; 312444c061aSmrg if (app_lock->stack.sp >= 0) { 313444c061aSmrg xcondition_signal (app_lock->stack.st[app_lock->stack.sp].c); 314444c061aSmrg } 315444c061aSmrg } 316444c061aSmrg#ifndef _XMUTEX_NESTS 317444c061aSmrg xmutex_unlock(app_lock->mutex); 318444c061aSmrg#endif 319444c061aSmrg} 320444c061aSmrg 321444c061aSmrgstatic void 322444c061aSmrgFreeAppLock(XtAppContext app) 323444c061aSmrg{ 324444c061aSmrg unsigned ii; 325444c061aSmrg LockPtr app_lock = app->lock_info; 326444c061aSmrg 327444c061aSmrg if(app_lock) { 328444c061aSmrg xmutex_clear(app_lock->mutex); 329444c061aSmrg xmutex_free(app_lock->mutex); 330444c061aSmrg#ifndef _XMUTEX_NESTS 331444c061aSmrg xcondition_clear(app_lock->cond); 332444c061aSmrg xcondition_free(app_lock->cond); 333444c061aSmrg#endif 334444c061aSmrg if(app_lock->stack.st != (struct _Tstack *)NULL) { 335444c061aSmrg for (ii = 0; ii < app_lock->stack.size; ii++) { 336444c061aSmrg xcondition_clear(app_lock->stack.st[ii].c); 337444c061aSmrg xcondition_free(app_lock->stack.st[ii].c); 338444c061aSmrg } 339444c061aSmrg XtFree((char *)app_lock->stack.st); 340444c061aSmrg } 341444c061aSmrg XtFree((char *)app_lock); 342444c061aSmrg app->lock_info = NULL; 343444c061aSmrg } 344444c061aSmrg} 345444c061aSmrg 346444c061aSmrgstatic void 347444c061aSmrgInitAppLock(XtAppContext app) 348444c061aSmrg{ 349444c061aSmrg int ii; 350444c061aSmrg LockPtr app_lock; 351444c061aSmrg 352444c061aSmrg app->lock = AppLock; 353444c061aSmrg app->unlock = AppUnlock; 354444c061aSmrg app->yield_lock = YieldAppLock; 355444c061aSmrg app->restore_lock = RestoreAppLock; 356444c061aSmrg app->free_lock = FreeAppLock; 357444c061aSmrg 358444c061aSmrg app_lock = app->lock_info = XtNew(LockRec); 359444c061aSmrg app_lock->mutex = xmutex_malloc(); 360444c061aSmrg xmutex_init(app_lock->mutex); 361444c061aSmrg app_lock->level = 0; 362444c061aSmrg#ifndef _XMUTEX_NESTS 363444c061aSmrg app_lock->cond = xcondition_malloc(); 364444c061aSmrg xcondition_init(app_lock->cond); 365444c061aSmrg xthread_clear_id(app_lock->holder); 366444c061aSmrg#endif 367444c061aSmrg app_lock->stack.size = STACK_INCR; 368444c061aSmrg app_lock->stack.sp = -1; 369444c061aSmrg app_lock->stack.st = 370444c061aSmrg (struct _Tstack *)__XtMalloc(sizeof(struct _Tstack)*STACK_INCR); 371444c061aSmrg for (ii = 0; ii < STACK_INCR; ii++) { 372444c061aSmrg app_lock->stack.st[ii].c = xcondition_malloc(); 373444c061aSmrg xcondition_init(app_lock->stack.st[ii].c); 374444c061aSmrg } 375444c061aSmrg} 376444c061aSmrg 377444c061aSmrg#endif /* defined(XTHREADS) */ 378444c061aSmrg 379444c061aSmrgvoid XtAppLock(XtAppContext app) 380444c061aSmrg{ 381444c061aSmrg#ifdef XTHREADS 382444c061aSmrg if(app->lock) 383444c061aSmrg (*app->lock)(app); 384444c061aSmrg#endif 385444c061aSmrg} 386444c061aSmrg 387444c061aSmrgvoid XtAppUnlock(XtAppContext app) 388444c061aSmrg{ 389444c061aSmrg#ifdef XTHREADS 390444c061aSmrg if(app->unlock) 391444c061aSmrg (*app->unlock)(app); 392444c061aSmrg#endif 393444c061aSmrg} 394444c061aSmrg 395444c061aSmrgvoid XtProcessLock(void) 396444c061aSmrg{ 397444c061aSmrg#ifdef XTHREADS 398444c061aSmrg if(_XtProcessLock) 399444c061aSmrg (*_XtProcessLock)(); 400444c061aSmrg#endif 401444c061aSmrg} 402444c061aSmrg 403444c061aSmrgvoid XtProcessUnlock(void) 404444c061aSmrg{ 405444c061aSmrg#ifdef XTHREADS 406444c061aSmrg if(_XtProcessUnlock) 407444c061aSmrg (*_XtProcessUnlock)(); 408444c061aSmrg#endif 409444c061aSmrg} 410444c061aSmrg 411444c061aSmrgBoolean XtToolkitThreadInitialize(void) 412444c061aSmrg{ 413444c061aSmrg#ifdef XTHREADS 414444c061aSmrg if (_XtProcessLock == NULL) { 415444c061aSmrg#ifdef xthread_init 416444c061aSmrg xthread_init(); 417444c061aSmrg#endif 418444c061aSmrg InitProcessLock(); 419444c061aSmrg _XtProcessLock = ProcessLock; 420444c061aSmrg _XtProcessUnlock = ProcessUnlock; 421444c061aSmrg _XtInitAppLock = InitAppLock; 422444c061aSmrg } 423444c061aSmrg return True; 424444c061aSmrg#else 425444c061aSmrg return False; 426444c061aSmrg#endif 427444c061aSmrg} 428444c061aSmrg 429