📄 ethread.h
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * Description: Thread library for use in the ERTS and other OTP * applications. * Author: Rickard Green */#ifndef ETHREAD_H__#define ETHREAD_H__#ifndef ETHR_HAVE_ETHREAD_DEFINES# include "ethread_header_config.h"#endif#include <stdlib.h>#include <errno.h>typedef struct { long tv_sec; long tv_nsec;} ethr_timeval;#if defined(DEBUG)# undef ETHR_XCHK# define ETHR_XCHK 1#else# ifndef ETHR_XCHK# define ETHR_XCHK 0# endif#endif#undef ETHR_INLINE#if defined(__GNUC__)# define ETHR_INLINE __inline__#elif defined(__WIN32__)# define ETHR_INLINE __forceinline#endif#if defined(DEBUG) || !defined(ETHR_INLINE) || ETHR_XCHK# undef ETHR_TRY_INLINE_FUNCS#endif#define ETHR_RWMUTEX_INITIALIZED 0x99999999#define ETHR_MUTEX_INITIALIZED 0x77777777#define ETHR_COND_INITIALIZED 0x55555555#if defined(ETHR_PTHREADS)/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * The pthread implementation *\* */#if defined(__linux__) && !defined(_GNU_SOURCE)#error "_GNU_SOURCE not defined. Please, compile all files with -D_GNU_SOURCE."#endif#if defined(ETHR_HAVE_MIT_PTHREAD_H)#include <pthread/mit/pthread.h>#elif defined(ETHR_HAVE_PTHREAD_H)#include <pthread.h>#endif#define ETHR_HAVE_ETHR_MUTEX_TRYLOCK 1/* Types */typedef pthread_t ethr_tid;typedef struct ethr_mutex_ ethr_mutex;struct ethr_mutex_ { pthread_mutex_t pt_mtx; int is_rec_mtx; ethr_mutex *prev; ethr_mutex *next;#if ETHR_XCHK int initialized;#endif};typedef struct ethr_cond_ ethr_cond;struct ethr_cond_ { pthread_cond_t pt_cnd;#if ETHR_XCHK int initialized;#endif};#ifdef ETHR_EXTENDED_LIBtypedef struct ethr_rwmutex_ ethr_rwmutex;struct ethr_rwmutex_ { pthread_rwlock_t pt_rwlock;#if ETHR_XCHK int initialized;#endif};#endif/* Static initializers */#if ETHR_XCHK#define ETHR_MUTEX_XCHK_INITER , ETHR_MUTEX_INITIALIZED#define ETHR_COND_XCHK_INITER , ETHR_COND_INITIALIZED#else#define ETHR_MUTEX_XCHK_INITER#define ETHR_COND_XCHK_INITER#endif#define ETHR_MUTEX_INITER {PTHREAD_MUTEX_INITIALIZER, 0, NULL, NULL ETHR_MUTEX_XCHK_INITER}#define ETHR_COND_INITER {PTHREAD_COND_INITIALIZER ETHR_COND_XCHK_INITER}#if defined(ETHR_HAVE_PTHREAD_MUTEXATTR_SETTYPE) \ || defined(ETHR_HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)# define ETHR_HAVE_ETHR_REC_MUTEX_INIT 1# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP# define ETHR_REC_MUTEX_INITER \ {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, 1, NULL, NULL ETHR_MUTEX_XCHK_INITER}# endif#else# undef ETHR_HAVE_ETHR_REC_MUTEX_INIT#endif#ifndef ETHR_HAVE_PTHREAD_ATFORK# define ETHR_NO_FORKSAFETY 1#endiftypedef pthread_key_t ethr_tsd_key;#define ETHR_HAVE_ETHR_SIG_FUNCS 1#ifdef ETHR_EXTENDED_LIB#if (!defined(__builtin_expect) \ || !defined(__GNUC__) \ || (__GNUC__ < 3 && __GNUC_MINOR__ < 96))#define __builtin_expect(X, Y) (X)#endif/* For CPU-optimised atomics, spinlocks, and rwlocks. */#if defined(__GNUC__)#if defined(__i386__)#include "i386/ethread.h"#elif defined(__x86_64__)#include "x86_64/ethread.h"#elif (defined(__powerpc__) || defined(__ppc__)) && !defined(__powerpc64__)#include "ppc32/ethread.h"#elif defined(__sparc__)#include "sparc32/ethread.h"#endif#endif /* __GNUC__ */#if defined(PURIFY) || defined(VALGRIND) || defined(ETHR_DISABLE_NATIVE_OPS)#undef ETHR_HAVE_NATIVE_ATOMICS#undef ETHR_HAVE_NATIVE_LOCKS#endif#ifdef ETHR_HAVE_NATIVE_ATOMICS/* * Map ethread native atomics to ethread API atomics. */typedef ethr_native_atomic_t ethr_atomic_t;static ETHR_INLINE intethr_atomic_init(ethr_atomic_t *var, long i){ ethr_native_atomic_init(var, i); return 0;}static ETHR_INLINE intethr_atomic_set(ethr_atomic_t *var, long i){ ethr_native_atomic_set(var, i); return 0;}static ETHR_INLINE intethr_atomic_read(ethr_atomic_t *var, long *i){ *i = ethr_native_atomic_read(var); return 0;}static ETHR_INLINE intethr_atomic_add(ethr_atomic_t *var, long incr){ ethr_native_atomic_add(var, incr); return 0;} static ETHR_INLINE intethr_atomic_addtest(ethr_atomic_t *var, long i, long *testp){ *testp = ethr_native_atomic_add_return(var, i); return 0;}static ETHR_INLINE intethr_atomic_inc(ethr_atomic_t *var){ ethr_native_atomic_inc(var); return 0;}static ETHR_INLINE intethr_atomic_dec(ethr_atomic_t *var){ ethr_native_atomic_dec(var); return 0;}static ETHR_INLINE intethr_atomic_inctest(ethr_atomic_t *var, long *testp){ *testp = ethr_native_atomic_inc_return(var); return 0;}static ETHR_INLINE intethr_atomic_dectest(ethr_atomic_t *var, long *testp){ *testp = ethr_native_atomic_dec_return(var); return 0;}static ETHR_INLINE intethr_atomic_and_old(ethr_atomic_t *var, long mask, long *old){ *old = ethr_native_atomic_and_retold(var, mask); return 0;}static ETHR_INLINE intethr_atomic_or_old(ethr_atomic_t *var, long mask, long *old){ *old = ethr_native_atomic_or_retold(var, mask); return 0;}static ETHR_INLINE intethr_atomic_xchg(ethr_atomic_t *var, long new, long *old){ *old = ethr_native_atomic_xchg(var, new); return 0;} #define ETHR_HAVE_OPTIMIZED_ATOMIC_OPS 1#endif /* ETHR_HAVE_NATIVE_ATOMICS */#ifdef ETHR_HAVE_NATIVE_LOCKS/* * Map ethread native spinlocks to ethread API spinlocks. */typedef ethr_native_spinlock_t ethr_spinlock_t;static ETHR_INLINE intethr_spinlock_init(ethr_spinlock_t *lock){ ethr_native_spinlock_init(lock); return 0;}static ETHR_INLINE intethr_spinlock_destroy(ethr_spinlock_t *lock){ return 0;}static ETHR_INLINE intethr_spin_unlock(ethr_spinlock_t *lock){ ethr_native_spin_unlock(lock); return 0;}static ETHR_INLINE intethr_spin_lock(ethr_spinlock_t *lock){ ethr_native_spin_lock(lock); return 0;}/* * Map ethread native rwlocks to ethread API rwlocks. */typedef ethr_native_rwlock_t ethr_rwlock_t;static ETHR_INLINE intethr_rwlock_init(ethr_rwlock_t *lock){ ethr_native_rwlock_init(lock); return 0;}static ETHR_INLINE intethr_rwlock_destroy(ethr_rwlock_t *lock){ return 0;}static ETHR_INLINE intethr_read_unlock(ethr_rwlock_t *lock){ ethr_native_read_unlock(lock); return 0;}static ETHR_INLINE intethr_read_lock(ethr_rwlock_t *lock){ ethr_native_read_lock(lock); return 0;}static ETHR_INLINE intethr_write_unlock(ethr_rwlock_t *lock){ ethr_native_write_unlock(lock); return 0;}static ETHR_INLINE intethr_write_lock(ethr_rwlock_t *lock){ ethr_native_write_lock(lock); return 0;}#define ETHR_HAVE_OPTIMIZED_LOCKS 1#endif /* ETHR_HAVE_NATIVE_LOCKS */#endif /* #ifdef ETHR_EXTENDED_LIB */#ifndef ETHR_HAVE_OPTIMIZED_ATOMIC_OPS#define ETHR_ATOMIC_ADDR_BITS 4#define ETHR_ATOMIC_ADDR_SHIFT 3#ifdef ETHR_HAVE_PTHREAD_SPIN_LOCKextern pthread_spinlock_t ethr_atomic_spinlock[1 << ETHR_ATOMIC_ADDR_BITS];#define ETHR_ATOMIC_PTR2LCK__(PTR) \(ðr_atomic_spinlock[((((unsigned long) (PTR)) >> ETHR_ATOMIC_ADDR_SHIFT) \ & ((1 << ETHR_ATOMIC_ADDR_BITS) - 1))])#define ETHR_ATOMIC_OP_FALLBACK_IMPL__(AP, EXPS) \do { \ pthread_spinlock_t *slp__ = ETHR_ATOMIC_PTR2LCK__((AP)); \ int res__ = pthread_spin_lock(slp__); \ if (res__ != 0) \ return res__; \ { EXPS; } \ return pthread_spin_unlock(slp__); \} while (0)#elseextern pthread_mutex_t ethr_atomic_mutex[1 << ETHR_ATOMIC_ADDR_BITS];#define ETHR_ATOMIC_PTR2LCK__(PTR) \(ðr_atomic_mutex[((((unsigned long) (PTR)) >> ETHR_ATOMIC_ADDR_SHIFT) \ & ((1 << ETHR_ATOMIC_ADDR_BITS) - 1))])#define ETHR_ATOMIC_OP_FALLBACK_IMPL__(AP, EXPS) \do { \ pthread_mutex_t *mtxp__ = ETHR_ATOMIC_PTR2LCK__((AP)); \ int res__ = pthread_mutex_lock(mtxp__); \ if (res__ != 0) \ return res__; \ { EXPS; } \ return pthread_mutex_unlock(mtxp__); \} while (0)#endiftypedef long ethr_atomic_t;#endif#ifndef ETHR_HAVE_OPTIMIZED_LOCKS#ifdef ETHR_HAVE_PTHREAD_SPIN_LOCKtypedef struct { pthread_spinlock_t spnlck;} ethr_spinlock_t;typedef struct { pthread_spinlock_t spnlck; unsigned counter;} ethr_rwlock_t;#define ETHR_RWLOCK_WRITERS (((unsigned) 1) << 31)#elsetypedef struct { pthread_mutex_t mtx;} ethr_spinlock_t;typedef struct { pthread_rwlock_t rwlck;} ethr_rwlock_t;#endif#endif#ifdef ETHR_TRY_INLINE_FUNCSstatic ETHR_INLINE intethr_mutex_trylock(ethr_mutex *mtx){ return pthread_mutex_trylock(&mtx->pt_mtx);}static ETHR_INLINE intethr_mutex_lock(ethr_mutex *mtx){ return pthread_mutex_lock(&mtx->pt_mtx);}static ETHR_INLINE intethr_mutex_unlock(ethr_mutex *mtx){ return pthread_mutex_unlock(&mtx->pt_mtx);}#ifdef ETHR_EXTENDED_LIBstatic ETHR_INLINE intethr_rwmutex_tryrlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_tryrdlock(&rwmtx->pt_rwlock);}static ETHR_INLINE intethr_rwmutex_rlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_rdlock(&rwmtx->pt_rwlock);}static ETHR_INLINE intethr_rwmutex_runlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_unlock(&rwmtx->pt_rwlock);}static ETHR_INLINE intethr_rwmutex_tryrwlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_trywrlock(&rwmtx->pt_rwlock);}static ETHR_INLINE intethr_rwmutex_rwlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_wrlock(&rwmtx->pt_rwlock);}static ETHR_INLINE intethr_rwmutex_rwunlock(ethr_rwmutex *rwmtx){ return pthread_rwlock_unlock(&rwmtx->pt_rwlock);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -