⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_threads.h

📁 OTP是开放电信平台的简称
💻 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: Error checking thread interface to the ethread library. *              All functions terminates the emulator on failure. * Author: Rickard Green */#ifndef ERL_THREAD_H__#define ERL_THREAD_H__#include "sys.h"#ifdef USE_THREADS#define ETHR_TRY_INLINE_FUNCS#include "ethread.h"#include "erl_lock_check.h"#include "erl_term.h"#define ERTS_THR_OPTS_DEFAULT_INITER ETHR_THR_OPTS_DEFAULT_INITERtypedef ethr_thr_opts erts_thr_opts_t;typedef ethr_init_data erts_thr_init_data_t;typedef ethr_tid erts_tid_t;typedef struct {    ethr_mutex mtx;#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_lock_t lc;#endif} erts_mtx_t;typedef ethr_cond erts_cnd_t;typedef ethr_tsd_key erts_tsd_key_t;typedef ethr_timeval erts_thr_timeval_t;void  __noreturn erts_thr_fatal_error(int, char *); /* implemented in						       erl_init.c */#ifdef ERTS_ENABLE_LOCK_CHECK#define ERTS_REC_MTX_INITER \  {ETHR_REC_MUTEX_INITER, \   ERTS_LC_LOCK_INIT(-1,THE_NON_VALUE,ERTS_LC_FLG_LT_MUTEX)}#define ERTS_MTX_INITER \  {ETHR_MUTEX_INITER, \   ERTS_LC_LOCK_INIT(-1, THE_NON_VALUE, ERTS_LC_FLG_LT_MUTEX)}#else#define ERTS_REC_MTX_INITER		{ETHR_REC_MUTEX_INITER}#define ERTS_MTX_INITER			{ETHR_MUTEX_INITER}#endif#define ERTS_CND_INITER			ETHR_COND_INITER#define ERTS_THR_INIT_DATA_DEF_INITER	ETHR_INIT_DATA_DEFAULT_INITER#ifdef ETHR_HAVE_ETHR_REC_MUTEX_INIT#  define ERTS_HAVE_REC_MTX_INIT	ETHR_HAVE_ETHR_REC_MUTEX_INIT#endif#ifdef ETHR_HAVE_ETHR_MUTEX_TRYLOCK#  define ERTS_HAVE_MTX_TRYLOCK		ETHR_HAVE_ETHR_MUTEX_TRYLOCK#endif#else /* #ifdef USE_THREADS */#define ERTS_THR_OPTS_DEFAULT_INITER 0typedef int erts_thr_opts_t;typedef int erts_thr_init_data_t;typedef int erts_tid_t;typedef int erts_mtx_t;typedef int erts_cnd_t;typedef int erts_tsd_key_t;typedef struct {    long tv_sec;    long tv_nsec;} erts_thr_timeval_t;#define ERTS_REC_MTX_INITER		0#define ERTS_MTX_INITER			0#define ERTS_CND_INITER			0#define ERTS_THR_INIT_DATA_DEF_INITER	0#define ERTS_HAVE_REC_MTX_INIT		1#define ERTS_HAVE_MTX_TRYLOCK		1#endif /* #ifdef USE_THREADS */ERTS_GLB_INLINE void erts_thr_init(erts_thr_init_data_t *id);ERTS_GLB_INLINE void erts_thr_create(erts_tid_t *tid, void * (*func)(void *),				     void *arg, erts_thr_opts_t *opts);ERTS_GLB_INLINE void erts_thr_join(erts_tid_t tid, void **thr_res);ERTS_GLB_INLINE void erts_thr_detach(erts_tid_t tid);ERTS_GLB_INLINE void erts_thr_exit(void *res);ERTS_GLB_INLINE void erts_thr_install_exit_handler(void (*exit_handler)(void));ERTS_GLB_INLINE erts_tid_t erts_thr_self(void);ERTS_GLB_INLINE int erts_equal_tids(erts_tid_t x, erts_tid_t y);#ifdef ERTS_HAVE_REC_MTX_INITERTS_GLB_INLINE void erts_rec_mtx_init(erts_mtx_t *mtx);#endifERTS_GLB_INLINE void erts_mtx_init_x(erts_mtx_t *mtx, char *name, Eterm extra);ERTS_GLB_INLINE void erts_mtx_init_locked_x(erts_mtx_t *mtx,					    char *name,					    Eterm extra);ERTS_GLB_INLINE void erts_mtx_init(erts_mtx_t *mtx, char *name);ERTS_GLB_INLINE void erts_mtx_init_locked(erts_mtx_t *mtx, char *name);ERTS_GLB_INLINE void erts_mtx_destroy(erts_mtx_t *mtx);ERTS_GLB_INLINE void erts_mtx_set_forksafe(erts_mtx_t *mtx);ERTS_GLB_INLINE void erts_mtx_unset_forksafe(erts_mtx_t *mtx);#ifdef ERTS_HAVE_MTX_TRYLOCKERTS_GLB_INLINE int erts_mtx_trylock(erts_mtx_t *mtx);#endif /* #ifdef ETHR_HAVE_ETHR_MTX_TRYLOCK */ERTS_GLB_INLINE void erts_mtx_lock(erts_mtx_t *mtx);ERTS_GLB_INLINE void erts_mtx_unlock(erts_mtx_t *mtx);ERTS_GLB_INLINE int erts_lc_mtx_is_locked(erts_mtx_t *mtx);ERTS_GLB_INLINE void erts_cnd_init(erts_cnd_t *cnd);ERTS_GLB_INLINE void erts_cnd_destroy(erts_cnd_t *cnd);ERTS_GLB_INLINE void erts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx);ERTS_GLB_INLINE int erts_cnd_timedwait(erts_cnd_t *cnd, erts_mtx_t *mtx,				       erts_thr_timeval_t *time);ERTS_GLB_INLINE void erts_cnd_signal(erts_cnd_t *cnd);ERTS_GLB_INLINE void erts_cnd_broadcast(erts_cnd_t *cnd);ERTS_GLB_INLINE void erts_thr_time_now(erts_thr_timeval_t *time);ERTS_GLB_INLINE void erts_tsd_key_create(erts_tsd_key_t *keyp);ERTS_GLB_INLINE void erts_tsd_key_delete(erts_tsd_key_t key);ERTS_GLB_INLINE void erts_tsd_set(erts_tsd_key_t key, void *value);ERTS_GLB_INLINE void * erts_tsd_get(erts_tsd_key_t key);#ifdef ETHR_HAVE_ETHR_SIG_FUNCS#define ERTS_THR_HAVE_SIG_FUNCS 1ERTS_GLB_INLINE void erts_thr_sigmask(int how, const sigset_t *set,				      sigset_t *oset);ERTS_GLB_INLINE void erts_thr_sigwait(const sigset_t *set, int *sig);#endif /* #ifdef HAVE_ETHR_SIG_FUNCS */#if ERTS_GLB_INLINE_INCL_FUNC_DEFERTS_GLB_INLINE voiderts_thr_init(erts_thr_init_data_t *id){#ifdef USE_THREADS    int res = ethr_init(id);    if (res)	erts_thr_fatal_error(res, "initialize thread library");#endif}ERTS_GLB_INLINE voiderts_thr_create(erts_tid_t *tid, void * (*func)(void *), void *arg,		erts_thr_opts_t *opts){#ifdef USE_THREADS    int res = ethr_thr_create(tid, func, arg, opts);    if (res)	erts_thr_fatal_error(res, "create thread");#endif}ERTS_GLB_INLINE voiderts_thr_join(erts_tid_t tid, void **thr_res){#ifdef USE_THREADS    int res = ethr_thr_join(tid, thr_res);    if (res)	erts_thr_fatal_error(res, "join thread");#endif}ERTS_GLB_INLINE voiderts_thr_detach(erts_tid_t tid){#ifdef USE_THREADS    int res = ethr_thr_detach(tid);    if (res)	erts_thr_fatal_error(res, "detach thread");#endif}ERTS_GLB_INLINE voiderts_thr_exit(void *res){#ifdef USE_THREADS    ethr_thr_exit(res);    erts_thr_fatal_error(0, "terminate thread");#endif}ERTS_GLB_INLINE voiderts_thr_install_exit_handler(void (*exit_handler)(void)){#ifdef USE_THREADS    int res = ethr_install_exit_handler(exit_handler);    if (res != 0)	erts_thr_fatal_error(res, "install thread exit handler");#endif}ERTS_GLB_INLINE erts_tid_terts_thr_self(void){#ifdef USE_THREADS    return ethr_self();#else    return 0;#endif}ERTS_GLB_INLINE interts_equal_tids(erts_tid_t x, erts_tid_t y){#ifdef USE_THREADS    return ethr_equal_tids(x, y);#else    return 1;#endif}#ifdef ERTS_HAVE_REC_MTX_INITERTS_GLB_INLINE voiderts_rec_mtx_init(erts_mtx_t *mtx){#ifdef USE_THREADS    int res = ethr_rec_mutex_init(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "initialize recursive mutex");#endif}#endifERTS_GLB_INLINE voiderts_mtx_init_x(erts_mtx_t *mtx, char *name, Eterm extra){#ifdef USE_THREADS    int res = ethr_mutex_init(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "initialize mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_init_lock_x(&mtx->lc, name, ERTS_LC_FLG_LT_MUTEX, extra);#endif#endif}ERTS_GLB_INLINE voiderts_mtx_init_locked_x(erts_mtx_t *mtx, char *name, Eterm extra){#ifdef USE_THREADS    int res = ethr_mutex_init(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "initialize mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_init_lock_x(&mtx->lc, name, ERTS_LC_FLG_LT_MUTEX, extra);#endif    res = ethr_mutex_lock(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "lock mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_trylock(1, &mtx->lc);#endif#endif}ERTS_GLB_INLINE voiderts_mtx_init(erts_mtx_t *mtx, char *name){#ifdef USE_THREADS    int res = ethr_mutex_init(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "initialize mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_init_lock(&mtx->lc, name, ERTS_LC_FLG_LT_MUTEX);#endif#endif}ERTS_GLB_INLINE voiderts_mtx_init_locked(erts_mtx_t *mtx, char *name){#ifdef USE_THREADS    int res = ethr_mutex_init(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "initialize mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_init_lock(&mtx->lc, name, ERTS_LC_FLG_LT_MUTEX);#endif    res = ethr_mutex_lock(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "lock mutex");#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_trylock(1, &mtx->lc);#endif#endif}ERTS_GLB_INLINE voiderts_mtx_destroy(erts_mtx_t *mtx){#ifdef USE_THREADS    int res;#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_destroy_lock(&mtx->lc);#endif    res = ethr_mutex_destroy(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "destroy mutex");#endif}ERTS_GLB_INLINE voiderts_mtx_set_forksafe(erts_mtx_t *mtx){#ifdef USE_THREADS    int res = ethr_mutex_set_forksafe(&mtx->mtx);    if (res != 0 && res != ENOTSUP)	erts_thr_fatal_error(res, "set mutex forksafe");#endif}ERTS_GLB_INLINE voiderts_mtx_unset_forksafe(erts_mtx_t *mtx){#ifdef USE_THREADS    int res = ethr_mutex_unset_forksafe(&mtx->mtx);    if (res != 0 && res != ENOTSUP)	erts_thr_fatal_error(res, "unset mutex forksafe");#endif}#ifdef ERTS_HAVE_MTX_TRYLOCKERTS_GLB_INLINE interts_mtx_trylock(erts_mtx_t *mtx){#ifdef USE_THREADS    int res;#ifdef ERTS_ENABLE_LOCK_CHECK    if (erts_lc_trylock_force_busy(&mtx->lc))	return EBUSY; /* Make sure caller can handle the situation without			 causing a lock order violation */#endif    res = ethr_mutex_trylock(&mtx->mtx);#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_trylock(res == 0, &mtx->lc);#endif    if (res != 0 && res != EBUSY)	erts_thr_fatal_error(res, "try lock mutex");        return res;#else    return 0;#endif}#endif /* #ifdef ETHR_HAVE_ETHR_MTX_TRYLOCK */ERTS_GLB_INLINE voiderts_mtx_lock(erts_mtx_t *mtx){#ifdef USE_THREADS    int res;#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_lock(&mtx->lc);#endif    res = ethr_mutex_lock(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "lock mutex");#endif}ERTS_GLB_INLINE voiderts_mtx_unlock(erts_mtx_t *mtx){#ifdef USE_THREADS    int res;#ifdef ERTS_ENABLE_LOCK_CHECK    erts_lc_unlock(&mtx->lc);#endif    res = ethr_mutex_unlock(&mtx->mtx);    if (res)	erts_thr_fatal_error(res, "unlock mutex");#endif}ERTS_GLB_INLINE interts_lc_mtx_is_locked(erts_mtx_t *mtx){#if defined(USE_THREADS) && defined(ERTS_ENABLE_LOCK_CHECK)    int res;    erts_lc_lock_t lc = mtx->lc;    lc.flags = 0;    erts_lc_have_locks(&res, &lc, 1);    return res;#else    return 0;#endif}ERTS_GLB_INLINE voiderts_cnd_init(erts_cnd_t *cnd){#ifdef USE_THREADS    int res = ethr_cond_init(cnd);    if (res)	erts_thr_fatal_error(res, "initialize condition variable");#endif}ERTS_GLB_INLINE voiderts_cnd_destroy(erts_cnd_t *cnd){#ifdef USE_THREADS    int res = ethr_cond_destroy(cnd);    if (res)	erts_thr_fatal_error(res, "destroy condition variable");#endif}ERTS_GLB_INLINE voiderts_cnd_wait(erts_cnd_t *cnd, erts_mtx_t *mtx){#ifdef USE_THREADS    int res = ethr_cond_wait(cnd, &mtx->mtx);    if (res != 0 && res != EINTR)	erts_thr_fatal_error(res, "wait on condition variable");#endif}ERTS_GLB_INLINE interts_cnd_timedwait(erts_cnd_t *cnd, erts_mtx_t *mtx, erts_thr_timeval_t *time){#ifdef USE_THREADS    int res = ethr_cond_timedwait(cnd, &mtx->mtx, time);    if (res != 0 && res != EINTR && res != ETIMEDOUT)	erts_thr_fatal_error(res,			     "wait with timeout on condition variable");    return res;#else    return 0;#endif}ERTS_GLB_INLINE voiderts_cnd_signal(erts_cnd_t *cnd){#ifdef USE_THREADS    int res = ethr_cond_signal(cnd);    if (res)	erts_thr_fatal_error(res, "signal on condition variable");#endif}ERTS_GLB_INLINE voiderts_cnd_broadcast(erts_cnd_t *cnd){#ifdef USE_THREADS    int res = ethr_cond_broadcast(cnd);    if (res)	erts_thr_fatal_error(res, "broadcast on condition variable");#endif}ERTS_GLB_INLINE voiderts_thr_time_now(erts_thr_timeval_t *time){#ifdef USE_THREADS    int res = ethr_time_now(time);    if (res)	erts_thr_fatal_error(res, "get current time");#endif}ERTS_GLB_INLINE voiderts_tsd_key_create(erts_tsd_key_t *keyp){#ifdef USE_THREADS    int res = ethr_tsd_key_create(keyp);    if (res)	erts_thr_fatal_error(res, "create thread specific data key");#endif}ERTS_GLB_INLINE voiderts_tsd_key_delete(erts_tsd_key_t key){#ifdef USE_THREADS    int res = ethr_tsd_key_delete(key);    if (res)	erts_thr_fatal_error(res, "delete thread specific data key");#endif}ERTS_GLB_INLINE voiderts_tsd_set(erts_tsd_key_t key, void *value){#ifdef USE_THREADS    int res = ethr_tsd_set(key, value);    if (res)	erts_thr_fatal_error(res, "set thread specific data");#endif}ERTS_GLB_INLINE void *erts_tsd_get(erts_tsd_key_t key){#ifdef USE_THREADS    return ethr_tsd_get(key);#else    return NULL;#endif}#ifdef ETHR_HAVE_ETHR_SIG_FUNCSERTS_GLB_INLINE voiderts_thr_sigmask(int how, const sigset_t *set, sigset_t *oset){#ifdef USE_THREADS    int res = ethr_sigmask(how, set, oset);    if (res)	erts_thr_fatal_error(res, "get or set signal mask");#endif}ERTS_GLB_INLINE voiderts_thr_sigwait(const sigset_t *set, int *sig){#ifdef USE_THREADS    int res;    do {	res = ethr_sigwait(set, sig);    } while (res == EINTR);    if (res)	erts_thr_fatal_error(res, "to wait for signal");#endif}#endif /* #ifdef HAVE_ETHR_SIG_FUNCS */#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */#endif /* #ifndef ERL_THREAD_H__ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -