mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-29 18:24:42 +00:00
Introduce pthread_rwlock_try{rd,wr}lock
This also changes recursive mutexes to favor cpu over scheduler yield.
This commit is contained in:
parent
a1e1e821cb
commit
fadb64a2bf
13 changed files with 122 additions and 29 deletions
|
@ -145,6 +145,8 @@ o/$(MODE)/libc/calls/tailcontext.o: libc/calls/tailcontext.S
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
o/$(MODE)/libc/calls/stackjump.o: libc/calls/stackjump.S
|
o/$(MODE)/libc/calls/stackjump.o: libc/calls/stackjump.S
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
o/$(MODE)/libc/calls/sched_yield.o: libc/calls/sched_yield.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
|
||||||
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
|
|
@ -119,8 +119,6 @@ o/$(MODE)/libc/intrin/ksockoptnames.o: libc/intrin/ksockoptnames.S
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
o/$(MODE)/libc/intrin/ktcpoptnames.o: libc/intrin/ktcpoptnames.S
|
o/$(MODE)/libc/intrin/ktcpoptnames.o: libc/intrin/ktcpoptnames.S
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
o/$(MODE)/libc/intrin/sched_yield.o: libc/intrin/sched_yield.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
o/$(MODE)/libc/intrin/stackcall.o: libc/intrin/stackcall.S
|
o/$(MODE)/libc/intrin/stackcall.o: libc/intrin/stackcall.S
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
|
#include "libc/nexgen32e/yield.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
@ -64,7 +65,7 @@
|
||||||
* @see pthread_spin_lock()
|
* @see pthread_spin_lock()
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
*/
|
*/
|
||||||
int pthread_mutex_lock(pthread_mutex_t *mutex) {
|
errno_t pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
LOCKTRACE("pthread_mutex_lock(%t)", mutex);
|
LOCKTRACE("pthread_mutex_lock(%t)", mutex);
|
||||||
|
@ -82,7 +83,7 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||||
|
|
||||||
if (mutex->_type == PTHREAD_MUTEX_NORMAL) {
|
if (mutex->_type == PTHREAD_MUTEX_NORMAL) {
|
||||||
while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
||||||
pthread_yield();
|
spin_yield();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +103,7 @@ int pthread_mutex_lock(pthread_mutex_t *mutex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
while (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
||||||
pthread_yield();
|
spin_yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex->_depth = 0;
|
mutex->_depth = 0;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
@ -19,27 +19,29 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
#include "libc/intrin/kprintf.h"
|
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/thread/thread.h"
|
#include "libc/thread/thread.h"
|
||||||
#include "libc/thread/tls.h"
|
|
||||||
#include "third_party/nsync/mu.h"
|
#include "third_party/nsync/mu.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks mutex if it isn't locked already.
|
* Attempts acquiring lock.
|
||||||
*
|
*
|
||||||
* Unlike pthread_mutex_lock() this function won't block and instead
|
* Unlike pthread_mutex_lock() this function won't block and instead
|
||||||
* returns an error immediately if the lock couldn't be acquired.
|
* returns an error immediately if the lock couldn't be acquired.
|
||||||
*
|
*
|
||||||
* @return 0 on success, or errno on error
|
* @return 0 if lock was acquired, otherwise an errno
|
||||||
* @raise EBUSY if lock is already held
|
* @raise EAGAIN if maximum number of recursive locks is held
|
||||||
* @raise ENOTRECOVERABLE if `mutex` is corrupted
|
* @raise EBUSY if lock is currently held in read or write mode
|
||||||
|
* @raise EINVAL if `mutex` doesn't refer to an initialized lock
|
||||||
|
* @raise EDEADLK if `mutex` is `PTHREAD_MUTEX_ERRORCHECK` and the
|
||||||
|
* current thread already holds this mutex
|
||||||
*/
|
*/
|
||||||
errno_t pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
errno_t pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
if (__tls_enabled && //
|
// delegate to *NSYNC if possible
|
||||||
mutex->_type == PTHREAD_MUTEX_NORMAL && //
|
if (mutex->_type == PTHREAD_MUTEX_NORMAL &&
|
||||||
mutex->_pshared == PTHREAD_PROCESS_PRIVATE && //
|
mutex->_pshared == PTHREAD_PROCESS_PRIVATE && //
|
||||||
_weaken(nsync_mu_trylock)) {
|
_weaken(nsync_mu_trylock)) {
|
||||||
if (_weaken(nsync_mu_trylock)((nsync_mu *)mutex)) {
|
if (_weaken(nsync_mu_trylock)((nsync_mu *)mutex)) {
|
||||||
|
@ -49,6 +51,7 @@ errno_t pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle normal mutexes
|
||||||
if (mutex->_type == PTHREAD_MUTEX_NORMAL) {
|
if (mutex->_type == PTHREAD_MUTEX_NORMAL) {
|
||||||
if (!atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
if (!atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -57,6 +60,7 @@ errno_t pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle recursive and error check mutexes
|
||||||
t = gettid();
|
t = gettid();
|
||||||
if (mutex->_owner == t) {
|
if (mutex->_owner == t) {
|
||||||
if (mutex->_type != PTHREAD_MUTEX_ERRORCHECK) {
|
if (mutex->_type != PTHREAD_MUTEX_ERRORCHECK) {
|
||||||
|
@ -67,15 +71,17 @@ errno_t pthread_mutex_trylock(pthread_mutex_t *mutex) {
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return EBUSY;
|
return EDEADLK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
if (atomic_exchange_explicit(&mutex->_lock, 1, memory_order_acquire)) {
|
||||||
mutex->_depth = 0;
|
|
||||||
mutex->_owner = t;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex->_depth = 0;
|
||||||
|
mutex->_owner = t;
|
||||||
|
mutex->_pid = __pid;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
* @raises EPERM if in error check mode and not owned by caller
|
* @raises EPERM if in error check mode and not owned by caller
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
*/
|
*/
|
||||||
int pthread_mutex_unlock(pthread_mutex_t *mutex) {
|
errno_t pthread_mutex_unlock(pthread_mutex_t *mutex) {
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
LOCKTRACE("pthread_mutex_unlock(%t)", mutex);
|
LOCKTRACE("pthread_mutex_unlock(%t)", mutex);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
|
#include "libc/nexgen32e/yield.h"
|
||||||
#include "libc/thread/posixthread.internal.h"
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
|
||||||
intptr_t _pthread_syshand(struct PosixThread *pt) {
|
intptr_t _pthread_syshand(struct PosixThread *pt) {
|
||||||
|
@ -27,6 +28,6 @@ intptr_t _pthread_syshand(struct PosixThread *pt) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
syshand = atomic_load_explicit(&pt->tib->tib_syshand, memory_order_acquire);
|
syshand = atomic_load_explicit(&pt->tib->tib_syshand, memory_order_acquire);
|
||||||
if (syshand) return syshand;
|
if (syshand) return syshand;
|
||||||
pthread_yield();
|
spin_yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/intrin/atomic.h"
|
#include "libc/intrin/atomic.h"
|
||||||
|
#include "libc/nexgen32e/yield.h"
|
||||||
#include "libc/thread/posixthread.internal.h"
|
#include "libc/thread/posixthread.internal.h"
|
||||||
|
|
||||||
int _pthread_tid(struct PosixThread *pt) {
|
int _pthread_tid(struct PosixThread *pt) {
|
||||||
int tid = 0;
|
int tid = 0;
|
||||||
while (pt && !(tid = atomic_load_explicit(&pt->ptid, memory_order_acquire))) {
|
while (pt && !(tid = atomic_load_explicit(&pt->ptid, memory_order_acquire))) {
|
||||||
pthread_yield();
|
spin_yield();
|
||||||
}
|
}
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
|
|
||||||
__static_yoink("nsync_mu_lock");
|
__static_yoink("nsync_mu_lock");
|
||||||
__static_yoink("nsync_mu_unlock");
|
__static_yoink("nsync_mu_unlock");
|
||||||
|
__static_yoink("nsync_mu_trylock");
|
||||||
__static_yoink("nsync_mu_rlock");
|
__static_yoink("nsync_mu_rlock");
|
||||||
__static_yoink("nsync_mu_runlock");
|
__static_yoink("nsync_mu_runlock");
|
||||||
__static_yoink("_pthread_atfork");
|
__static_yoink("_pthread_atfork");
|
||||||
|
|
37
libc/thread/pthread_rwlock_tryrdlock.c
Normal file
37
libc/thread/pthread_rwlock_tryrdlock.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
#include "third_party/nsync/mu.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts acquiring read lock on read-write lock.
|
||||||
|
*
|
||||||
|
* @return 0 if lock was acquired, otherwise an errno
|
||||||
|
* @raise EBUSY if lock is currently held in write mode
|
||||||
|
* @raise EAGAIN if maximum number of read locks are held
|
||||||
|
* @raise EINVAL if `rwlock` doesn't refer to an initialized r/w lock
|
||||||
|
*/
|
||||||
|
errno_t pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) {
|
||||||
|
if (nsync_mu_rtrylock((nsync_mu *)rwlock)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
}
|
37
libc/thread/pthread_rwlock_trywrlock.c
Normal file
37
libc/thread/pthread_rwlock_trywrlock.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/thread/thread.h"
|
||||||
|
#include "third_party/nsync/mu.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts acquiring write lock on read-write lock.
|
||||||
|
*
|
||||||
|
* @return 0 if lock was acquired, otherwise an errno
|
||||||
|
* @raise EBUSY if lock is currently held in read or write mode
|
||||||
|
* @raise EINVAL if `rwlock` doesn't refer to an initialized r/w lock
|
||||||
|
*/
|
||||||
|
errno_t pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) {
|
||||||
|
if (nsync_mu_trylock((nsync_mu *)rwlock)) {
|
||||||
|
rwlock->_iswrite = 1;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,8 @@
|
||||||
#define THREADS 8
|
#define THREADS 8
|
||||||
#define ITERATIONS 512
|
#define ITERATIONS 512
|
||||||
|
|
||||||
|
#define MAX_RECURSIVE_LOCKS 64
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
atomic_int started;
|
atomic_int started;
|
||||||
atomic_int finished;
|
atomic_int finished;
|
||||||
|
@ -79,11 +81,18 @@ TEST(pthread_mutex_lock, recursive) {
|
||||||
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
|
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
|
||||||
ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
|
ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
|
||||||
ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
|
ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
|
||||||
|
for (int i = 0; i < MAX_RECURSIVE_LOCKS; ++i) {
|
||||||
|
if (i & 1) {
|
||||||
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
} else {
|
||||||
ASSERT_EQ(0, pthread_mutex_trylock(&lock));
|
ASSERT_EQ(0, pthread_mutex_trylock(&lock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT_EQ(EAGAIN, pthread_mutex_lock(&lock));
|
||||||
|
ASSERT_EQ(EAGAIN, pthread_mutex_trylock(&lock));
|
||||||
|
for (int i = 0; i < MAX_RECURSIVE_LOCKS; ++i) {
|
||||||
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
}
|
||||||
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
||||||
|
@ -99,7 +108,7 @@ TEST(pthread_mutex_lock, errorcheck) {
|
||||||
ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
|
ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
|
||||||
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
ASSERT_EQ(0, pthread_mutex_lock(&lock));
|
||||||
ASSERT_EQ(EDEADLK, pthread_mutex_lock(&lock));
|
ASSERT_EQ(EDEADLK, pthread_mutex_lock(&lock));
|
||||||
ASSERT_EQ(EBUSY, pthread_mutex_trylock(&lock));
|
ASSERT_EQ(EDEADLK, pthread_mutex_trylock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
|
||||||
ASSERT_EQ(0, pthread_mutex_destroy(&lock));
|
ASSERT_EQ(0, pthread_mutex_destroy(&lock));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue