nsprpub/pr/src/bthreads/btmon.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/src/bthreads/btmon.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,201 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include <kernel/OS.h>
    1.10 +
    1.11 +#include "primpl.h"
    1.12 +
    1.13 +/*
    1.14 +** Create a new monitor. Monitors are re-entrant locks with a single built-in
    1.15 +** condition variable.
    1.16 +**
    1.17 +** This may fail if memory is tight or if some operating system resource
    1.18 +** is low.
    1.19 +*/
    1.20 +PR_IMPLEMENT(PRMonitor*)
    1.21 +    PR_NewMonitor (void)
    1.22 +{
    1.23 +    PRMonitor *mon;
    1.24 +    PRCondVar *cvar;
    1.25 +    PRLock    *lock;
    1.26 +
    1.27 +    mon = PR_NEWZAP( PRMonitor );
    1.28 +    if( mon )
    1.29 +    {
    1.30 +	lock = PR_NewLock();
    1.31 +	if( !lock )
    1.32 +        {
    1.33 +	    PR_DELETE( mon );
    1.34 +	    return( 0 );
    1.35 +	}
    1.36 +
    1.37 +	cvar = PR_NewCondVar( lock );
    1.38 +	if( !cvar )
    1.39 +	{
    1.40 +	    PR_DestroyLock( lock );
    1.41 +	    PR_DELETE( mon );
    1.42 +	    return( 0 );
    1.43 +	}
    1.44 +
    1.45 +	mon->cvar = cvar;
    1.46 +	mon->name = NULL;
    1.47 +    }
    1.48 +
    1.49 +    return( mon );
    1.50 +}
    1.51 +
    1.52 +PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
    1.53 +{
    1.54 +    PRMonitor* mon = PR_NewMonitor();
    1.55 +    if( mon )
    1.56 +    {
    1.57 +        mon->name = name;
    1.58 +    }
    1.59 +    return mon;
    1.60 +}
    1.61 +
    1.62 +/*
    1.63 +** Destroy a monitor. The caller is responsible for guaranteeing that the
    1.64 +** monitor is no longer in use. There must be no thread waiting on the
    1.65 +** monitor's condition variable and that the lock is not held.
    1.66 +**
    1.67 +*/
    1.68 +PR_IMPLEMENT(void)
    1.69 +    PR_DestroyMonitor (PRMonitor *mon)
    1.70 +{
    1.71 +    PR_DestroyLock( mon->cvar->lock );
    1.72 +    PR_DestroyCondVar( mon->cvar );
    1.73 +    PR_DELETE( mon );
    1.74 +}
    1.75 +
    1.76 +/*
    1.77 +** Enter the lock associated with the monitor. If the calling thread currently
    1.78 +** is in the monitor, the call to enter will silently succeed. In either case,
    1.79 +** it will increment the entry count by one.
    1.80 +*/
    1.81 +PR_IMPLEMENT(void)
    1.82 +    PR_EnterMonitor (PRMonitor *mon)
    1.83 +{
    1.84 +    if( mon->cvar->lock->owner == find_thread( NULL ) )
    1.85 +    {
    1.86 +	mon->entryCount++;
    1.87 +
    1.88 +    } else
    1.89 +    {
    1.90 +	PR_Lock( mon->cvar->lock );
    1.91 +	mon->entryCount = 1;
    1.92 +    }
    1.93 +}
    1.94 +
    1.95 +/*
    1.96 +** Decrement the entry count associated with the monitor. If the decremented
    1.97 +** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
    1.98 +** calling thread has not entered the monitor.
    1.99 +*/
   1.100 +PR_IMPLEMENT(PRStatus)
   1.101 +    PR_ExitMonitor (PRMonitor *mon)
   1.102 +{
   1.103 +    if( mon->cvar->lock->owner != find_thread( NULL ) )
   1.104 +    {
   1.105 +	return( PR_FAILURE );
   1.106 +    }
   1.107 +    if( --mon->entryCount == 0 )
   1.108 +    {
   1.109 +	return( PR_Unlock( mon->cvar->lock ) );
   1.110 +    }
   1.111 +    return( PR_SUCCESS );
   1.112 +}
   1.113 +
   1.114 +/*
   1.115 +** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
   1.116 +** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
   1.117 +** indefinite).
   1.118 +**
   1.119 +** While the thread is waiting it exits the monitor (as if it called
   1.120 +** PR_ExitMonitor as many times as it had called PR_EnterMonitor).  When
   1.121 +** the wait has finished the thread regains control of the monitors lock
   1.122 +** with the same entry count as before the wait began.
   1.123 +**
   1.124 +** The thread waiting on the monitor will be resumed when the monitor is
   1.125 +** notified (assuming the thread is the next in line to receive the
   1.126 +** notify) or when the "ticks" timeout elapses.
   1.127 +**
   1.128 +** Returns PR_FAILURE if the caller has not entered the monitor.
   1.129 +*/
   1.130 +PR_IMPLEMENT(PRStatus)
   1.131 +    PR_Wait (PRMonitor *mon, PRIntervalTime ticks)
   1.132 +{
   1.133 +    PRUint32 entryCount;
   1.134 +    PRUintn  status;
   1.135 +    PRThread *meThread;
   1.136 +    thread_id me = find_thread( NULL );
   1.137 +    meThread = PR_GetCurrentThread();
   1.138 +
   1.139 +    if( mon->cvar->lock->owner != me ) return( PR_FAILURE );
   1.140 +
   1.141 +    entryCount = mon->entryCount;
   1.142 +    mon->entryCount = 0;
   1.143 +
   1.144 +    status = PR_WaitCondVar( mon->cvar, ticks );
   1.145 +
   1.146 +    mon->entryCount = entryCount;
   1.147 +
   1.148 +    return( status );
   1.149 +}
   1.150 +
   1.151 +/*
   1.152 +** Notify a thread waiting on the monitor's condition variable. If a thread
   1.153 +** is waiting on the condition variable (using PR_Wait) then it is awakened
   1.154 +** and attempts to reenter the monitor.
   1.155 +*/
   1.156 +PR_IMPLEMENT(PRStatus)
   1.157 +    PR_Notify (PRMonitor *mon)
   1.158 +{
   1.159 +    if( mon->cvar->lock->owner != find_thread( NULL ) )
   1.160 +    {
   1.161 +	return( PR_FAILURE );
   1.162 +    }
   1.163 +
   1.164 +    PR_NotifyCondVar( mon->cvar );
   1.165 +    return( PR_SUCCESS );
   1.166 +}
   1.167 +
   1.168 +/*
   1.169 +** Notify all of the threads waiting on the monitor's condition variable.
   1.170 +** All of threads waiting on the condition are scheduled to reenter the
   1.171 +** monitor.
   1.172 +*/
   1.173 +PR_IMPLEMENT(PRStatus)
   1.174 +    PR_NotifyAll (PRMonitor *mon)
   1.175 +{
   1.176 +    if( mon->cvar->lock->owner != find_thread( NULL ) )
   1.177 +    {
   1.178 +	return( PR_FAILURE );
   1.179 +    }
   1.180 +
   1.181 +    PR_NotifyAllCondVar( mon->cvar );
   1.182 +    return( PR_SUCCESS );
   1.183 +}
   1.184 +
   1.185 +/*
   1.186 +** Return the number of times that the current thread has entered the
   1.187 +** lock. Returns zero if the current thread has not entered the lock.
   1.188 +*/
   1.189 +PR_IMPLEMENT(PRIntn)
   1.190 +    PR_GetMonitorEntryCount(PRMonitor *mon)
   1.191 +{
   1.192 +    return( (mon->cvar->lock->owner == find_thread( NULL )) ?
   1.193 +            mon->entryCount : 0 );
   1.194 +}
   1.195 +
   1.196 +/*
   1.197 +** If the current thread is in |mon|, this assertion is guaranteed to
   1.198 +** succeed.  Otherwise, the behavior of this function is undefined.
   1.199 +*/
   1.200 +PR_IMPLEMENT(void)
   1.201 +    PR_AssertCurrentThreadInMonitor(PRMonitor *mon)
   1.202 +{
   1.203 +    PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mon->cvar->lock);
   1.204 +}

mercurial