📄 erl_process.h
字号:
erts_proc_lock(Process *p, Uint32 lock_flags){ Uint32 locks = lock_flags & ERTS_PROC_LOCKS_ALL; erts_proc_lock_t *lckp = &erts_proc_locks[ERTS_PID2LOCKIX(p->id)]; erts_smp_mtx_lock(&lckp->mtx); if (p->lock_flags & locks) (void) erts_proc_get_locks(p, lckp, lock_flags, 1);#ifdef ERTS_ENABLE_LOCK_CHECK else erts_proc_lc_lock(p, locks);#endif p->lock_flags |= lock_flags; erts_smp_mtx_unlock(&lckp->mtx);}ERTS_GLB_INLINE interts_proc_trylock(Process *p, Uint32 lock_flags){ int res; Uint32 locks = lock_flags & ERTS_PROC_LOCKS_ALL; erts_proc_lock_t *lckp = &erts_proc_locks[ERTS_PID2LOCKIX(p->id)]; erts_smp_mtx_lock(&lckp->mtx);#ifdef ERTS_ENABLE_LOCK_CHECK if (erts_proc_lc_trylock_force_busy(p, locks)) { res = EBUSY; /* Make sure caller can handle the situation without causing a lock order violation to occur */ } else#endif if (p->lock_flags & locks) { res = EBUSY; } else { p->lock_flags |= lock_flags; res = 0; }#ifdef ERTS_ENABLE_LOCK_CHECK erts_proc_lc_trylock(p, locks, res == 0);#endif erts_smp_mtx_unlock(&lckp->mtx); return res;}ERTS_GLB_INLINE voiderts_proc_unlock(Process *p, Uint32 lock_flags){ erts_proc_lock_t *lckp = &erts_proc_locks[ERTS_PID2LOCKIX(p->id)]; erts_smp_mtx_lock(&lckp->mtx);#ifdef ERTS_ENABLE_LOCK_CHECK erts_proc_lc_unlock(p, lock_flags & ERTS_PROC_LOCKS_ALL);#endif p->lock_flags &= ~lock_flags; if (p->lock_flags & ERTS_PROC_LOCK_FLAG_WAITERS) { erts_smp_cnd_broadcast(&lckp->cnd); /* erts_smp_cnd_signal() won't do since mtx, cnd pair is used for multiple locks. */ p->lock_flags &= ~ERTS_PROC_LOCK_FLAG_WAITERS; } erts_smp_mtx_unlock(&lckp->mtx);}#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */interts_proc_safelock(Process * this_proc, Uint32 this_have_locks, Uint32 this_need_locks, int allow_this_exiting, Uint32 other_pid, Process *other_proc, Uint32 other_have_locks, Uint32 other_need_locks, int allow_other_exiting);#endif /* #ifdef ERTS_SMP */#define ERTS_P2P_FLG_ALLOW_OTHER_X (((Uint32) 1) << 0)#ifdef ERTS_SMP/* * erts_pid2proc_opt(): * * Looks up the process structure of a pid and at the same time * acquires process locks. Locks on currently executing process and * looked up process are taken according to the lock order, i.e., * locks on currently executing process may have be released and * reacquired. Since all locks on currently executing process may * have to be released, it may become exiting. * * Arguments: * this_proc: Normally currently executing process, * but it can be any proc. * this_have_locks: currently aqired locks on this_proc * pid: pid of process to lookup * pid_need_locks: locks to acquire on looked up process * allow_this_exiting: If != 0, ignore if this_proc becomes * exiting. * * Return value: A pointer to process struct of * pid. * If a value != NULL is returned, * this_have_locks are acquired on this_proc * and pid_need_locks on looked up process. * Both processes are valid processes, * i.e. not in the states exiting or free. * If NULL is returned, either this_proc * became exiting, or no process could be * looked up. this_have_locks are acquired, * on this_proc. * If allow_other_exiting != 0, lookup * will proceed even if this_proc becomes * exiting, i.e., this_proc may have become * exiting even if a value != NULL is * returned. */ERTS_GLB_INLINE Process *erts_pid2proc_opt(Process *c_p, Uint32 c_p_have_locks, Eterm pid, Uint32 pid_need_locks, int flags);#if ERTS_GLB_INLINE_INCL_FUNC_DEFERTS_GLB_INLINE Process *erts_pid2proc_opt(Process *c_p, Uint32 c_p_have_locks, Eterm pid, Uint32 pid_need_locks, int flags){ erts_proc_lock_t *lckp; Uint32 need_locks; Uint pix; Process *proc; if (is_not_internal_pid(pid)) return NULL; pix = internal_pid_index(pid); if(pix >= erts_max_processes) return NULL; lckp = &erts_proc_locks[ERTS_PID2LOCKIX(pid)]; erts_smp_mtx_lock(&lckp->mtx); need_locks = pid_need_locks & ERTS_PROC_LOCKS_ALL; if (c_p && c_p->id == pid) { need_locks &= ~c_p_have_locks; proc = c_p; ASSERT(c_p->id != ERTS_INVALID_PID); ASSERT(c_p == process_tab[pix]); } else proc = process_tab[pix]; if (!proc || proc->id != pid || ((proc->lock_flags & ERTS_PROC_LOCK_FLAG_EXITING) && !(flags & ERTS_P2P_FLG_ALLOW_OTHER_X))) { proc = NULL; goto done; } if (#ifdef ERTS_ENABLE_LOCK_CHECK erts_proc_lc_trylock_force_busy(proc, need_locks) || /* Make sure erts_proc_safelock() is enough to handle a potential lock order violation situation... */#endif (proc->lock_flags & need_locks)) { erts_smp_mtx_unlock(&lckp->mtx); if (!erts_proc_safelock(c_p, c_p_have_locks, c_p_have_locks, 1, pid, proc, 0, need_locks, flags & ERTS_P2P_FLG_ALLOW_OTHER_X)) proc = NULL; } else { /* Got them all at once... */ proc->lock_flags |= need_locks;#ifdef ERTS_ENABLE_LOCK_CHECK if (need_locks) erts_proc_lc_trylock(proc, need_locks, 1);#endif done: erts_smp_mtx_unlock(&lckp->mtx); } return proc;}#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */Process *erts_pid2proc_not_running(Process *, Uint32, Eterm, Uint32);#ifdef DEBUG#define ERTS_SMP_ASSERT_IS_NOT_EXITING(P) \ do { ASSERT(!(P)->is_exiting); } while (0)#else#define ERTS_SMP_ASSERT_IS_NOT_EXITING(P)#endif/* NOTE: At least one process lock has to be held on P! */#ifdef ERTS_ENABLE_LOCK_CHECK#define ERTS_PROC_IS_EXITING(P) \ (ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks((P)) != 0), \ (P)->is_exiting)#else#define ERTS_PROC_IS_EXITING(P) ((P)->is_exiting)#endif#else /* !ERTS_SMP */#define ERTS_PROC_IS_EXITING(P) ((P)->status == P_EXITING)#define ERTS_SMP_ASSERT_IS_NOT_EXITING(P)#define erts_pid2proc_not_running erts_pid2proc#endif#define erts_pid2proc(PROC, HL, PID, NL) \ erts_pid2proc_opt((PROC), (HL), (PID), (NL), 0)ERTS_GLB_INLINE Process *#ifdef ERTS_SMPerts_pid2proc_unlocked_opt(Eterm pid, int flags);#elseerts_pid2proc_opt(Process *c_p_unused, Uint32 c_p_have_locks_unused, Eterm pid, Uint32 pid_need_locks_unused, int flags);#endif#if ERTS_GLB_INLINE_INCL_FUNC_DEFERTS_GLB_INLINE Process *#ifdef ERTS_SMPerts_pid2proc_unlocked_opt(Eterm pid, int flags)#elseerts_pid2proc_opt(Process *c_p_unused, Uint32 c_p_have_locks_unused, Eterm pid, Uint32 pid_need_locks_unused, int flags)#endif{ Uint pix; Process *proc; if (is_not_internal_pid(pid)) return NULL; pix = internal_pid_index(pid); if(pix >= erts_max_processes) return NULL; proc = process_tab[pix]; if (proc) { if (proc->id != pid || (!(flags & ERTS_P2P_FLG_ALLOW_OTHER_X) && proc->status == P_EXITING)) proc = NULL; } return proc;}#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */#ifdef ERTS_SMP#define erts_pid2proc_unlocked(PID) erts_pid2proc_unlocked_opt((PID), 0)#else#define erts_pid2proc_unlocked(PID) erts_pid2proc_opt(NULL, 0, (PID), 0, 0)#endif/* Minimum NUMBER of processes for a small system to start */#ifdef ERTS_SMP#define ERTS_MIN_PROCESSES ERTS_PROC_LOCKS_BITS#else#define ERTS_MIN_PROCESSES 16#endif/* Process locks */ERTS_GLB_INLINE void erts_smp_proc_lock(Process *p, Uint32 locks);ERTS_GLB_INLINE void erts_smp_proc_unlock(Process *p, Uint32 locks);ERTS_GLB_INLINE int erts_smp_proc_trylock(Process *p, Uint32 locks);ERTS_GLB_INLINE void erts_smp_proc_tab_lock(void);ERTS_GLB_INLINE void erts_smp_proc_tab_unlock(void);#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS/* Scheduling lock */extern erts_smp_mtx_t schdlq_mtx;#ifdef ERTS_SMPextern int erts_all_schedulers_waiting;#endifERTS_GLB_INLINE int erts_smp_sched_trylock(void);ERTS_GLB_INLINE void erts_smp_sched_lock(void);ERTS_GLB_INLINE void erts_smp_sched_unlock(void);ERTS_GLB_INLINE void erts_smp_notify_inc_runq(void);#if defined(ERTS_SMP) && defined(ERTS_ENABLE_LOCK_CHECK)int erts_smp_is_sched_locked(void);#endifvoid erts_wake_one_scheduler(void);#endif /* ERTS_INCLUDE_SCHEDULER_INTERNALS */#if ERTS_GLB_INLINE_INCL_FUNC_DEFERTS_GLB_INLINE voiderts_smp_proc_lock(Process *p, Uint32 locks){#ifdef ERTS_SMP erts_proc_lock(p, locks);#endif}ERTS_GLB_INLINE voiderts_smp_proc_unlock(Process *p, Uint32 locks){#ifdef ERTS_SMP erts_proc_unlock(p, locks);#endif}ERTS_GLB_INLINE interts_smp_proc_trylock(Process *p, Uint32 locks){#ifdef ERTS_SMP return erts_proc_trylock(p, locks);#else return 0;#endif}ERTS_GLB_INLINE voiderts_smp_proc_tab_lock(void){#ifdef ERTS_SMP int i; for (i = 0; i < ERTS_PROC_LOCKS_NO_OF; i++) erts_smp_mtx_lock(&erts_proc_locks[i].mtx);#endif}ERTS_GLB_INLINE voiderts_smp_proc_tab_unlock(void){#ifdef ERTS_SMP int i; for (i = ERTS_PROC_LOCKS_NO_OF - 1; i >= 0; i--) erts_smp_mtx_unlock(&erts_proc_locks[i].mtx);#endif}#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALSERTS_GLB_INLINE interts_smp_sched_trylock(void){#ifdef ERTS_SMP return erts_smp_mtx_trylock(&schdlq_mtx);#else return 0;#endif}ERTS_GLB_INLINE voiderts_smp_sched_lock(void){#ifdef ERTS_SMP erts_smp_mtx_lock(&schdlq_mtx);#endif}ERTS_GLB_INLINE voiderts_smp_sched_unlock(void){#ifdef ERTS_SMP erts_smp_mtx_unlock(&schdlq_mtx);#endif}ERTS_GLB_INLINE voiderts_smp_notify_inc_runq(void){#ifdef ERTS_SMP ERTS_SMP_LC_ASSERT(erts_smp_is_sched_locked()); if (erts_all_schedulers_waiting) erts_wake_one_scheduler();#endif}#endif /* ERTS_INCLUDE_SCHEDULER_INTERNALS */#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */#undef ERTS_INCLUDE_SCHEDULER_INTERNALS#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -