#include "kern/kern_trace.h"
#include <sys/syscall.h>
-#include "os/atomic.h"
-
#ifdef PLOCKSTAT
#include "plockstat.h"
#else /* !PLOCKSTAT */
#define PLOCKSTAT_MUTEX_RELEASE(x, y)
#endif /* PLOCKSTAT */
+#define PTHREAD_MUTEX_INIT_UNUSED 1
+
extern int __unix_conforming;
#ifndef BUILDING_VARIANT
MUTEX_GETSEQ_ADDR(_pthread_mutex *mutex,
volatile uint64_t **seqaddr)
{
- // addr of m_seq[1] for misaligned, m_seq[0] for aligned mutex struct
- *seqaddr = (volatile uint64_t *)(((uintptr_t)&mutex->m_seq[1]) & ~0x7ul);
+ // 64-bit aligned address inside m_seq array (&m_seq[0] for aligned mutex)
+ // We don't require more than byte alignment on OS X. rdar://22278325
+ *seqaddr = (volatile uint64_t*)(((uintptr_t)mutex->m_seq + 0x7ul) & ~0x7ul);
}
PTHREAD_ALWAYS_INLINE
MUTEX_GETTID_ADDR(_pthread_mutex *mutex,
volatile uint64_t **tidaddr)
{
- // addr of m_tid[1] for misaligned, m_tid[0] for aligned mutex struct
- *tidaddr = (volatile uint64_t *)(((uintptr_t)&mutex->m_tid[1]) & ~0x7ul);
+ // 64-bit aligned address inside m_tid array (&m_tid[0] for aligned mutex)
+ // We don't require more than byte alignment on OS X. rdar://22278325
+ *tidaddr = (volatile uint64_t*)(((uintptr_t)mutex->m_tid + 0x7ul) & ~0x7ul);
}
#ifndef BUILDING_VARIANT /* [ */
return EBUSY;
#endif
_pthread_mutex *mutex = (_pthread_mutex *)omutex;
- LOCK_INIT(mutex->lock);
+ _PTHREAD_LOCK_INIT(mutex->lock);
return (_pthread_mutex_init(mutex, attr, 0x7));
}
int res = EINVAL;
_pthread_mutex *mutex = (_pthread_mutex *)omutex;
if (_pthread_mutex_check_signature(mutex)) {
- LOCK(mutex->lock);
+ _PTHREAD_LOCK(mutex->lock);
*prioceiling = mutex->prioceiling;
res = 0;
- UNLOCK(mutex->lock);
+ _PTHREAD_UNLOCK(mutex->lock);
}
return res;
}
int res = EINVAL;
_pthread_mutex *mutex = (_pthread_mutex *)omutex;
if (_pthread_mutex_check_signature(mutex)) {
- LOCK(mutex->lock);
+ _PTHREAD_LOCK(mutex->lock);
if (prioceiling >= -999 || prioceiling <= 999) {
*old_prioceiling = mutex->prioceiling;
mutex->prioceiling = prioceiling;
res = 0;
}
- UNLOCK(mutex->lock);
+ _PTHREAD_UNLOCK(mutex->lock);
}
return res;
}
_pthread_mutex *mutex = (_pthread_mutex *)omutex;
if (_pthread_mutex_check_signature_init(mutex)) {
- LOCK(mutex->lock);
+ _PTHREAD_LOCK(mutex->lock);
if (_pthread_mutex_check_signature_init(mutex)) {
// initialize a statically initialized mutex to provide
// compatibility for misbehaving applications.
} else if (_pthread_mutex_check_signature(mutex)) {
res = 0;
}
- UNLOCK(mutex->lock);
+ _PTHREAD_UNLOCK(mutex->lock);
} else if (_pthread_mutex_check_signature(mutex)) {
res = 0;
}
static inline int
-_pthread_mutex_init(_pthread_mutex *mutex, const pthread_mutexattr_t *attr, uint32_t static_type)
+_pthread_mutex_init(_pthread_mutex *mutex, const pthread_mutexattr_t *attr,
+ uint32_t static_type)
{
+ mutex->mtxopts.value = 0;
+ mutex->mtxopts.options.mutex = 1;
if (attr) {
if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG) {
return EINVAL;
}
mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
}
-
- mutex->mtxopts.options.notify = 0;
- mutex->mtxopts.options.unused = 0;
- mutex->mtxopts.options.hold = 0;
- mutex->mtxopts.options.mutex = 1;
- mutex->mtxopts.options.lock_count = 0;
-
- mutex->m_tid[0] = 0;
- mutex->m_tid[1] = 0;
- mutex->m_seq[0] = 0;
- mutex->m_seq[1] = 0;
- mutex->m_seq[2] = 0;
- mutex->prioceiling = 0;
mutex->priority = 0;
- mutex->mtxopts.options.misalign = (((uintptr_t)&mutex->m_seq[0]) & 0x7ul) != 0;
- if (mutex->mtxopts.options.misalign) {
- mutex->m_tid[0] = ~0u;
- } else {
- mutex->m_seq[2] = ~0u;
+ volatile uint64_t *seqaddr;
+ MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
+ volatile uint64_t *tidaddr;
+ MUTEX_GETTID_ADDR(mutex, &tidaddr);
+#if PTHREAD_MUTEX_INIT_UNUSED
+ if ((uint32_t*)tidaddr != mutex->m_tid) {
+ mutex->mtxopts.options.misalign = 1;
+ __builtin_memset(mutex->m_tid, 0xff, sizeof(mutex->m_tid));
}
+ __builtin_memset(mutex->m_mis, 0xff, sizeof(mutex->m_mis));
+#endif // PTHREAD_MUTEX_INIT_UNUSED
+ *tidaddr = 0;
+ *seqaddr = 0;
long sig = _PTHREAD_MUTEX_SIG;
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL &&
sig = _PTHREAD_MUTEX_SIG_fast;
}
- // unused, purely for detecting copied mutexes and smashes during debugging:
- mutex->reserved2[0] = ~(uintptr_t)mutex; // use ~ to hide from leaks
- mutex->reserved2[1] = (uintptr_t)sig;
+#if PTHREAD_MUTEX_INIT_UNUSED
+ // For detecting copied mutexes and smashes during debugging
+ uint32_t sig32 = (uint32_t)sig;
+#if defined(__LP64__)
+ uintptr_t guard = ~(uintptr_t)mutex; // use ~ to hide from leaks
+ __builtin_memcpy(mutex->_reserved, &guard, sizeof(guard));
+ mutex->_reserved[2] = sig32;
+ mutex->_reserved[3] = sig32;
+ mutex->_pad = sig32;
+#else
+ mutex->_reserved[0] = sig32;
+#endif
+#endif // PTHREAD_MUTEX_INIT_UNUSED
// Ensure all contents are properly set before setting signature.
#if defined(__LP64__)
int res = EINVAL;
- LOCK(mutex->lock);
+ _PTHREAD_LOCK(mutex->lock);
if (_pthread_mutex_check_signature(mutex)) {
uint32_t lgenval, ugenval;
uint64_t oldval64;
mutex->sig = _PTHREAD_NO_SIG;
res = 0;
}
- UNLOCK(mutex->lock);
+ _PTHREAD_UNLOCK(mutex->lock);
return res;
}