diff options
Diffstat (limited to 'src/Threads.c')
-rw-r--r-- | src/Threads.c | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/src/Threads.c b/src/Threads.c new file mode 100644 index 0000000..2fca1fb --- /dev/null +++ b/src/Threads.c @@ -0,0 +1,473 @@ +/* $Xorg: Threads.c,v 1.4 2001/02/09 02:03:59 xorgcvs Exp $ */ + +/************************************************************ +Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the name Sun not be used in advertising +or publicity pertaining to distribution of the software +without specific prior written permission. Sun makes no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#include "IntrinsicI.h" + +#ifdef XTHREADS + +#define xmalloc __XtMalloc +#define xfree XtFree +#include <X11/Xthreads.h> + +#ifndef NDEBUG +#define NDEBUG +#endif +#include <assert.h> +#include <stdio.h> + +typedef struct _ThreadStack { + unsigned int size; + int sp; + struct _Tstack { + xthread_t t; + xcondition_t c; + } *st; +} ThreadStack; + +typedef struct _LockRec { + xmutex_t mutex; + int level; + ThreadStack stack; +#ifndef _XMUTEX_NESTS + xthread_t holder; + xcondition_t cond; +#endif +} LockRec; + + +#define STACK_INCR 16 + +static LockPtr process_lock = NULL; + +static void +InitProcessLock() +{ + if(!process_lock) { + process_lock = XtNew(LockRec); + process_lock->mutex = xmutex_malloc(); + xmutex_init(process_lock->mutex); + process_lock->level = 0; +#ifndef _XMUTEX_NESTS + process_lock->cond = xcondition_malloc(); + xcondition_init(process_lock->cond); + xthread_clear_id(process_lock->holder); +#endif + } +} + +static void +ProcessLock() +{ +#ifdef _XMUTEX_NESTS + xmutex_lock(process_lock->mutex); + process_lock->level++; +#else + xthread_t this_thread = xthread_self(); + + xmutex_lock(process_lock->mutex); + + if (!xthread_have_id(process_lock->holder)) { + process_lock->holder = this_thread; + xmutex_unlock(process_lock->mutex); + return; + } + + if (xthread_equal(process_lock->holder,this_thread)) { + process_lock->level++; + xmutex_unlock(process_lock->mutex); + return; + } + + while(xthread_have_id(process_lock->holder)) + xcondition_wait(process_lock->cond, process_lock->mutex); + + process_lock->holder = this_thread; + assert(xthread_equal(process_lock->holder, this_thread)); + xmutex_unlock(process_lock->mutex); +#endif +} + +static void +ProcessUnlock() +{ +#ifdef _XMUTEX_NESTS + process_lock->level--; + xmutex_unlock(process_lock->mutex); +#else + xmutex_lock(process_lock->mutex); + assert(xthread_equal(process_lock->holder, xthread_self())); + if (process_lock->level != 0) { + process_lock->level--; + xmutex_unlock(process_lock->mutex); + return; + } + + xthread_clear_id(process_lock->holder); + xcondition_signal(process_lock->cond); + + xmutex_unlock(process_lock->mutex); +#endif +} + + +static void +#if NeedFunctionPrototypes +AppLock( + XtAppContext app) +#else +AppLock(app) + XtAppContext app; +#endif +{ + LockPtr app_lock = app->lock_info; +#ifdef _XMUTEX_NESTS + xmutex_lock(app_lock->mutex); + app_lock->level++; +#else + xthread_t self = xthread_self(); + xmutex_lock(app_lock->mutex); + if (!xthread_have_id(app_lock->holder)) { + app_lock->holder = self; + assert(xthread_equal(app_lock->holder, self)); + xmutex_unlock(app_lock->mutex); + return; + } + if (xthread_equal(app_lock->holder, self)) { + app_lock->level++; + xmutex_unlock(app_lock->mutex); + return; + } + while(xthread_have_id(app_lock->holder)) { + xcondition_wait(app_lock->cond, app_lock->mutex); + } + app_lock->holder = self; + assert(xthread_equal(app_lock->holder, self)); + xmutex_unlock(app_lock->mutex); +#endif +} + +static void +#if NeedFunctionPrototypes +AppUnlock( + XtAppContext app) +#else +AppUnlock(app) + XtAppContext app; +#endif +{ + LockPtr app_lock = app->lock_info; +#ifdef _XMUTEX_NESTS + app_lock->level--; + xmutex_unlock(app_lock->mutex); +#else + xthread_t self = xthread_self(); + xmutex_lock(app_lock->mutex); + assert(xthread_equal(app_lock->holder, self)); + if (app_lock->level != 0) { + app_lock->level--; + xmutex_unlock(app_lock->mutex); + return; + } + xthread_clear_id(app_lock->holder); + xcondition_signal(app_lock->cond); + xmutex_unlock(app_lock->mutex); +#endif +} + +static void +#if NeedFunctionPrototypes +YieldAppLock( + XtAppContext app, + Boolean* push_thread, + Boolean* pushed_thread, + int* level) +#else +YieldAppLock(app, push_thread, pushed_thread, level) + XtAppContext app; + Boolean* push_thread; + Boolean* pushed_thread; + int* level; +#endif +{ + LockPtr app_lock = app->lock_info; + xthread_t self = xthread_self(); +#ifndef _XMUTEX_NESTS + xmutex_lock(app_lock->mutex); + assert(xthread_equal(app_lock->holder, self)); +#endif + *level = app_lock->level; + if (*push_thread) { + *push_thread = FALSE; + *pushed_thread = TRUE; + + if(app_lock->stack.sp == app_lock->stack.size - 1) { + int ii; + app_lock->stack.st = (struct _Tstack *) + XtRealloc ((char *)app_lock->stack.st, + (app_lock->stack.size + STACK_INCR) * sizeof (struct _Tstack)); + ii = app_lock->stack.size; + app_lock->stack.size += STACK_INCR; + for ( ; ii < app_lock->stack.size; ii++) { + app_lock->stack.st[ii].c = xcondition_malloc(); + xcondition_init(app_lock->stack.st[ii].c); + } + } + app_lock->stack.st[++(app_lock->stack.sp)].t = self; + } +#ifdef _XMUTEX_NESTS + while (app_lock->level > 0) { + app_lock->level--; + xmutex_unlock(app_lock->mutex); + } +#else + xcondition_signal(app_lock->cond); + app_lock->level = 0; + xthread_clear_id(app_lock->holder); + xmutex_unlock(app_lock->mutex); +#endif +} + +static void +#if NeedFunctionPrototypes +RestoreAppLock( + XtAppContext app, + int level, + Boolean* pushed_thread) +#else +RestoreAppLock(app, level, pushed_thread) + XtAppContext app; + int level; + Boolean* pushed_thread; +#endif +{ + LockPtr app_lock = app->lock_info; + xthread_t self = xthread_self(); + xmutex_lock(app_lock->mutex); +#ifdef _XMUTEX_NESTS + app_lock->level++; +#else + while(xthread_have_id(app_lock->holder)) { + xcondition_wait(app_lock->cond, app_lock->mutex); + } +#endif + if (!xthread_equal(app_lock->stack.st[app_lock->stack.sp].t, self)) { + int ii; + for (ii = app_lock->stack.sp - 1; ii >= 0; ii--) { + if (xthread_equal(app_lock->stack.st[ii].t, self)) { + xcondition_wait(app_lock->stack.st[ii].c, app_lock->mutex); + break; + } + } +#ifndef _XMUTEX_NESTS + while(xthread_have_id(app_lock->holder)) { + xcondition_wait(app_lock->cond, app_lock->mutex); + } +#endif + } +#ifdef _XMUTEX_NESTS + while (app_lock->level < level) { + xmutex_lock(app_lock->mutex); + app_lock->level++; + } +#else + app_lock->holder = self; + app_lock->level = level; + assert(xthread_equal(app_lock->holder, self)); +#endif + if (*pushed_thread) { + *pushed_thread = FALSE; + (app_lock->stack.sp)--; + if (app_lock->stack.sp >= 0) { + xcondition_signal (app_lock->stack.st[app_lock->stack.sp].c); + } + } +#ifndef _XMUTEX_NESTS + xmutex_unlock(app_lock->mutex); +#endif +} + +static void +#if NeedFunctionPrototypes +FreeAppLock( + XtAppContext app) +#else +FreeAppLock(app) + XtAppContext app; +#endif +{ + int ii; + LockPtr app_lock = app->lock_info; + + if(app_lock) { + xmutex_clear(app_lock->mutex); + xmutex_free(app_lock->mutex); +#ifndef _XMUTEX_NESTS + xcondition_clear(app_lock->cond); + xcondition_free(app_lock->cond); +#endif + if(app_lock->stack.st != (struct _Tstack *)NULL) { + for (ii = 0; ii < app_lock->stack.size; ii++) { + xcondition_clear(app_lock->stack.st[ii].c); + xcondition_free(app_lock->stack.st[ii].c); + } + XtFree((char *)app_lock->stack.st); + } + XtFree((char *)app_lock); + app->lock_info = NULL; + } +} + +static void +#if NeedFunctionPrototypes +InitAppLock( + XtAppContext app) +#else +InitAppLock(app) + XtAppContext app; +#endif +{ + int ii; + LockPtr app_lock; + + app->lock = AppLock; + app->unlock = AppUnlock; + app->yield_lock = YieldAppLock; + app->restore_lock = RestoreAppLock; + app->free_lock = FreeAppLock; + + app_lock = app->lock_info = XtNew(LockRec); + app_lock->mutex = xmutex_malloc(); + xmutex_init(app_lock->mutex); + app_lock->level = 0; +#ifndef _XMUTEX_NESTS + app_lock->cond = xcondition_malloc(); + xcondition_init(app_lock->cond); + xthread_clear_id(app_lock->holder); +#endif + app_lock->stack.size = STACK_INCR; + app_lock->stack.sp = -1; + app_lock->stack.st = + (struct _Tstack *)__XtMalloc(sizeof(struct _Tstack)*STACK_INCR); + for (ii = 0; ii < STACK_INCR; ii++) { + app_lock->stack.st[ii].c = xcondition_malloc(); + xcondition_init(app_lock->stack.st[ii].c); + } +} + +#endif /* defined(XTHREADS) */ + +#if NeedFunctionPrototypes +void XtAppLock( + XtAppContext app) +#else +void XtAppLock(app) + XtAppContext app; +#endif +{ +#ifdef XTHREADS + if(app->lock) + (*app->lock)(app); +#endif +} + +#if NeedFunctionPrototypes +void XtAppUnlock( + XtAppContext app) +#else +void XtAppUnlock(app) + XtAppContext app; +#endif +{ +#ifdef XTHREADS + if(app->unlock) + (*app->unlock)(app); +#endif +} + +void XtProcessLock() +{ +#ifdef XTHREADS + if(_XtProcessLock) + (*_XtProcessLock)(); +#endif +} + +void XtProcessUnlock() +{ +#ifdef XTHREADS + if(_XtProcessUnlock) + (*_XtProcessUnlock)(); +#endif +} + +Boolean XtToolkitThreadInitialize() +{ +#ifdef XTHREADS + if (_XtProcessLock == NULL) { +#ifdef xthread_init + xthread_init(); +#endif + InitProcessLock(); + _XtProcessLock = ProcessLock; + _XtProcessUnlock = ProcessUnlock; + _XtInitAppLock = InitAppLock; + } + return True; +#else + return False; +#endif +} + |