Files
Amberelle Mason ac30ff9032 Initial import
Initial import of SunOS 4.1.1 and TME 0.8
2023-05-01 12:16:40 -04:00

141 lines
5.3 KiB
C

/* $Id: token.h,v 1.3 2010/06/05 19:37:27 fredette Exp $ */
/* tme/token.h - header file for token functions: */
/*
* Copyright (c) 2008 Matt Fredette
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Matt Fredette.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _TME_TOKEN_H
#define _TME_TOKEN_H
#include <tme/common.h>
_TME_RCSID("$Id: token.h,v 1.3 2010/06/05 19:37:27 fredette Exp $");
/* includes: */
#include <tme/threads.h>
#include <tme/memory.h>
/* macros: */
/* this returns nonzero if a token is valid: */
#define tme_token_is_valid(token) \
(__tme_predict_true(!tme_memory_atomic_read_flag(&(token)->tme_token_invalid)))
/* this returns nonzero if a token is invalid: */
#define tme_token_is_invalid(token) \
(__tme_predict_false(tme_memory_atomic_read_flag(&(token)->tme_token_invalid)))
/* this internal macro busies or unbusies a token: */
#ifndef TME_NO_DEBUG_LOCKS
#define _tme_token_busy_change(token, x) \
do { \
assert ((!tme_memory_atomic_read_flag(&(token)->tme_token_busy))\
!= !(x)); \
tme_memory_atomic_write_flag(&(token)->tme_token_busy, x); \
(token)->_tme_token_busy_file = __FILE__; \
(token)->_tme_token_busy_line = __LINE__; \
} while (/* CONSTCOND */ 0)
#elif !TME_THREADS_COOPERATIVE
#define _tme_token_busy_change(token, x) \
tme_memory_atomic_write_flag(&(token)->tme_token_busy, x)
#else /* TME_THREADS_COOPERATIVE && defined(TME_NO_DEBUG_LOCKS) */
#define _tme_token_busy_change(token, x) \
do { } while (0 && tme_memory_atomic_read_flag(&(token)->tme_token_invalid) && (x))
#endif /* TME_THREADS_COOPERATIVE && defined(TME_NO_DEBUG_LOCKS) */
/* this busies a token: */
/* NB: a token must be busied before its validity can be checked.
tme_token_busy() automatically makes a write-before-read barrier on
the token to order itself with a subsequent tme_token_is_valid() or
tme_token_is_invalid(), and the caller generally won't need to make
any additional barrier to order reads after a validity check
(because tokens can only be asynchronously invalidated, not
validated). however, a caller may need to make write-before-write
barriers to order any writes before a tme_token_unbusy(): */
#define tme_token_busy(token) \
do { \
_tme_token_busy_change(token, TRUE); \
tme_memory_barrier(token, \
sizeof(*token), \
TME_MEMORY_BARRIER_WRITE_BEFORE_READ); \
} while (/* CONSTCOND */ 0)
/* this unbusies a token: */
#define tme_token_unbusy(token) _tme_token_busy_change(token, FALSE)
/* this invalidates a token without synchronizing: */
#define tme_token_invalidate_nosync(token) \
tme_memory_atomic_write_flag(&(token)->tme_token_invalid, TRUE)
/* types: */
/* a token: */
struct tme_token {
/* if this is nonzero, the token has been invalidated: */
tme_memory_atomic_flag_t tme_token_invalid;
#if !TME_THREADS_COOPERATIVE || !defined(TME_NO_DEBUG_LOCKS)
/* if this is nonzero, the token is busy: */
tme_memory_atomic_flag_t tme_token_busy;
/* this mutex synchronizes tme_token_invalidate() and
tme_token_invalid_clear(): */
tme_mutex_t tme_token_invalid_mutex;
#ifndef TME_NO_DEBUG_LOCKS
/* the file and line number of the last busier or unbusier: */
_tme_const char *_tme_token_busy_file;
unsigned long _tme_token_busy_line;
#endif /* !TME_NO_DEBUG_LOCKS */
#endif /* !TME_THREADS_COOPERATIVE || !defined(TME_NO_DEBUG_LOCKS) */
};
/* prototypes: */
void tme_token_init _TME_P((struct tme_token *));
void tme_token_invalidate _TME_P((struct tme_token *));
void tme_token_invalid_clear _TME_P((struct tme_token *));
/* this wrapper macro predicts that the token doesn't need to be
cleared: */
#define tme_token_invalid_clear(token) \
do { \
if (tme_token_is_invalid(token)) { \
tme_token_invalid_clear(token); \
} \
} while (/* CONSTCOND */ 0)
#endif /* !_TME_TOKEN_H */