1570af302Sopenharmony_ci#include "pthread_impl.h"
2570af302Sopenharmony_ci
3570af302Sopenharmony_ciint __pthread_mutex_trylock_owner(pthread_mutex_t *m)
4570af302Sopenharmony_ci{
5570af302Sopenharmony_ci	int old, own;
6570af302Sopenharmony_ci	int type = m->_m_type;
7570af302Sopenharmony_ci	pthread_t self = __pthread_self();
8570af302Sopenharmony_ci	int tid = self->tid;
9570af302Sopenharmony_ci
10570af302Sopenharmony_ci	old = m->_m_lock;
11570af302Sopenharmony_ci	own = old & 0x3fffffff;
12570af302Sopenharmony_ci#ifdef __LITEOS_A__
13570af302Sopenharmony_ci	if (own == tid) {
14570af302Sopenharmony_ci		if ((type&PTHREAD_MUTEX_TYPE_MASK) == PTHREAD_MUTEX_RECURSIVE) {
15570af302Sopenharmony_ci			if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
16570af302Sopenharmony_ci			m->_m_count++;
17570af302Sopenharmony_ci			return 0;
18570af302Sopenharmony_ci		}
19570af302Sopenharmony_ci	}
20570af302Sopenharmony_ci#else
21570af302Sopenharmony_ci	if (__is_mutex_destroyed(m->_m_type))
22570af302Sopenharmony_ci		__handle_using_destroyed_mutex(m, __FUNCTION__);
23570af302Sopenharmony_ci	if (own == tid) {
24570af302Sopenharmony_ci		if ((type&8) && m->_m_count<0) {
25570af302Sopenharmony_ci			old &= 0x40000000;
26570af302Sopenharmony_ci			m->_m_count = 0;
27570af302Sopenharmony_ci			goto success;
28570af302Sopenharmony_ci		}
29570af302Sopenharmony_ci		if ((type&3) == PTHREAD_MUTEX_RECURSIVE) {
30570af302Sopenharmony_ci			if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
31570af302Sopenharmony_ci			m->_m_count++;
32570af302Sopenharmony_ci			return 0;
33570af302Sopenharmony_ci		}
34570af302Sopenharmony_ci	}
35570af302Sopenharmony_ci#endif
36570af302Sopenharmony_ci	if (own == 0x3fffffff) return ENOTRECOVERABLE;
37570af302Sopenharmony_ci	if (own || (old && !(type & 4))) return EBUSY;
38570af302Sopenharmony_ci
39570af302Sopenharmony_ci	if (type & 128) {
40570af302Sopenharmony_ci		if (!self->robust_list.off) {
41570af302Sopenharmony_ci			self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next;
42570af302Sopenharmony_ci#ifndef __LITEOS_A__
43570af302Sopenharmony_ci			__syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long));
44570af302Sopenharmony_ci#endif
45570af302Sopenharmony_ci		}
46570af302Sopenharmony_ci		if (m->_m_waiters) tid |= 0x80000000;
47570af302Sopenharmony_ci		self->robust_list.pending = &m->_m_next;
48570af302Sopenharmony_ci	}
49570af302Sopenharmony_ci	tid |= old & 0x40000000;
50570af302Sopenharmony_ci
51570af302Sopenharmony_ci	if (a_cas(&m->_m_lock, old, tid) != old) {
52570af302Sopenharmony_ci		self->robust_list.pending = 0;
53570af302Sopenharmony_ci#ifndef __LITEOS_A__
54570af302Sopenharmony_ci		if ((type&12)==12 && m->_m_waiters) return ENOTRECOVERABLE;
55570af302Sopenharmony_ci#endif
56570af302Sopenharmony_ci		return EBUSY;
57570af302Sopenharmony_ci	}
58570af302Sopenharmony_ci
59570af302Sopenharmony_ci#ifndef __LITEOS_A__
60570af302Sopenharmony_cisuccess:
61570af302Sopenharmony_ci	if ((type&8) && m->_m_waiters) {
62570af302Sopenharmony_ci		int priv = (type & 128) ^ 128;
63570af302Sopenharmony_ci		__syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv);
64570af302Sopenharmony_ci		self->robust_list.pending = 0;
65570af302Sopenharmony_ci		return (type&4) ? ENOTRECOVERABLE : EBUSY;
66570af302Sopenharmony_ci	}
67570af302Sopenharmony_ci#endif
68570af302Sopenharmony_ci
69570af302Sopenharmony_ci	volatile void *next = self->robust_list.head;
70570af302Sopenharmony_ci	m->_m_next = next;
71570af302Sopenharmony_ci	m->_m_prev = &self->robust_list.head;
72570af302Sopenharmony_ci	if (next != &self->robust_list.head) *(volatile void *volatile *)
73570af302Sopenharmony_ci		((char *)next - sizeof(void *)) = &m->_m_next;
74570af302Sopenharmony_ci	self->robust_list.head = &m->_m_next;
75570af302Sopenharmony_ci	self->robust_list.pending = 0;
76570af302Sopenharmony_ci
77570af302Sopenharmony_ci	if (old) {
78570af302Sopenharmony_ci		m->_m_count = 0;
79570af302Sopenharmony_ci		return EOWNERDEAD;
80570af302Sopenharmony_ci	}
81570af302Sopenharmony_ci
82570af302Sopenharmony_ci	return 0;
83570af302Sopenharmony_ci}
84570af302Sopenharmony_ci
85570af302Sopenharmony_ciint __pthread_mutex_trylock(pthread_mutex_t *m)
86570af302Sopenharmony_ci{
87570af302Sopenharmony_ci	if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL)
88570af302Sopenharmony_ci		return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY;
89570af302Sopenharmony_ci	return __pthread_mutex_trylock_owner(m);
90570af302Sopenharmony_ci}
91570af302Sopenharmony_ci
92570af302Sopenharmony_ciweak_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
93