static void * tf (void *arg) { pthread_rwlock_t *r = arg; /* Timeout: 0.3 secs. */ struct timespec ts_start; xclock_gettime (CLOCK_REALTIME, &ts_start); const struct timespec ts_timeout = timespec_add (ts_start, make_timespec (0, 300000000)); TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_timeout), ETIMEDOUT); puts ("child: timedwrlock failed with ETIMEDOUT"); TEST_TIMESPEC_NOW_OR_AFTER (CLOCK_REALTIME, ts_timeout); struct timespec ts_invalid; xclock_gettime (CLOCK_REALTIME, &ts_invalid); ts_invalid.tv_sec += 10; /* Note that the following operation makes ts invalid. */ ts_invalid.tv_nsec += 1000000000; TEST_COMPARE (pthread_rwlock_timedwrlock (r, &ts_invalid), EINVAL); puts ("child: timedwrlock failed with EINVAL"); return NULL; }
static TACommandVerdict pthread_rwlock_timedwrlock_cmd(TAThread thread, TAInputStream stream) { pthread_rwlock_t* rwlock; TimeUnit delta; struct timespec timeout; int res; // Prepare rwlock = readPointer(&stream); delta = readTimeUnit(&stream); // Reading the relative time BEFORE_BLOCKED_TARGET_OPERATION(thread); timeout = addTimeUnit(thread->start_time, delta); // Get the absolute timeout value writeString(thread, "Ok"); sendResponse(thread); START_TARGET_OPERATION(thread); // Execute res = pthread_rwlock_timedwrlock(rwlock, &timeout); END_TARGET_OPERATION(thread); // Response writeDeferredReaction(thread, "pthread_rwlock_timedwrlock_return"); writeInt(thread, res); sendResponse(thread); return taDefaultVerdict; }
static TACommandVerdict pthread_rwlock_timedwrlock_bad_cmd(TAThread thread, TAInputStream stream) { pthread_rwlock_t* rwlock; int nsec; struct timespec timeout; int res; // Prepare rwlock = readPointer(&stream); nsec = readInt(&stream); timeout = thread->start_time; timeout.tv_sec += 2; timeout.tv_nsec = nsec; START_TARGET_OPERATION(thread); // Execute res = pthread_rwlock_timedwrlock(rwlock, &timeout); END_TARGET_OPERATION(thread); // Response writeInt(thread, res); sendResponse(thread); return taDefaultVerdict; }
int main() { pthread_t t; struct timespec abstime = { 0, 0 }; struct _timeb currSysTime; const DWORD NANOSEC_PER_MILLISEC = 1000000; _ftime(&currSysTime); abstime.tv_sec = currSysTime.time; abstime.tv_nsec = NANOSEC_PER_MILLISEC * currSysTime.millitm; abstime.tv_sec += 1; assert(pthread_rwlock_timedwrlock(&rwlock1, &abstime) == 0); assert(pthread_create(&t, NULL, func, NULL) == 0); Sleep(2000); assert(pthread_rwlock_unlock(&rwlock1) == 0); assert(washere == 1); return 0; }
static void * th (void *arg) { long int res = 0; int r; struct timespec t = { -2, 0 }; r = pthread_mutex_timedlock (&m1, &t); if (r != ETIMEDOUT) { puts ("pthread_mutex_timedlock did not return ETIMEDOUT"); res = 1; } r = pthread_rwlock_timedrdlock (&rw1, &t); if (r != ETIMEDOUT) { puts ("pthread_rwlock_timedrdlock did not return ETIMEDOUT"); res = 1; } r = pthread_rwlock_timedwrlock (&rw2, &t); if (r != ETIMEDOUT) { puts ("pthread_rwlock_timedwrlock did not return ETIMEDOUT"); res = 1; } return (void *) res; }
int main(int argc, char** argv) { int r; pthread_mutex_t mutex; pthread_rwlock_t rwlock; struct timespec abs_timeout; time(&abs_timeout.tv_sec); abs_timeout.tv_nsec = 0; abs_timeout.tv_sec += 10; r = pthread_rwlock_init(&rwlock, NULL); assert(r == 0); fprintf(stderr, "Locking rwlock via pthread_rwlock_wrlock().\n"); r = pthread_rwlock_wrlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); fprintf(stderr, "Locking rwlock via pthread_rwlock_trywrlock().\n"); r = pthread_rwlock_trywrlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); fprintf(stderr, "Locking rwlock via pthread_rwlock_timedwrlock().\n"); #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK r = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); #endif fprintf(stderr, "Locking rwlock via pthread_rwlock_rdlock().\n"); r = pthread_rwlock_rdlock(&rwlock); assert(r == 0); r = pthread_rwlock_rdlock(&rwlock); assert(r == 0); r = pthread_rwlock_rdlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); fprintf(stderr, "Locking rwlock via pthread_rwlock_tryrdlock().\n"); r = pthread_rwlock_tryrdlock(&rwlock); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); fprintf(stderr, "Locking rwlock via pthread_rwlock_timedrdlock().\n"); #ifdef HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK r = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); assert(r == 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); #endif fprintf(stderr, "Attempt to lock for writing recursively (not allowed).\n"); r = pthread_rwlock_wrlock(&rwlock); assert(r == 0); r = pthread_rwlock_wrlock(&rwlock); assert(r != 0); r = pthread_rwlock_unlock(&rwlock); assert(r == 0); r = pthread_rwlock_destroy(&rwlock); assert(r == 0); r = pthread_mutex_init(&mutex, NULL); assert(r == 0); fprintf(stderr, "Locking mutex via pthread_mutex_trylock().\n"); r = pthread_mutex_trylock(&mutex); assert(r == 0); r = pthread_mutex_unlock(&mutex); assert(r == 0); fprintf(stderr, "Locking mutex via pthread_mutex_lock().\n"); r = pthread_mutex_lock(&mutex); assert(r == 0); r = pthread_mutex_unlock(&mutex); assert(r == 0); fprintf(stderr, "Locking mutex via pthread_mutex_timedlock().\n"); #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK r = pthread_mutex_timedlock(&mutex, &abs_timeout); assert(r == 0); r = pthread_mutex_unlock(&mutex); assert(r == 0); #endif r = pthread_mutex_destroy(&mutex); assert(r == 0); return 0; }
bool rw_mutex::impl::write_lock(double sec) { #if defined(__linux__) || defined(__sparcv8) || defined(__sparcv9) if (!valid) return false; #ifdef JUBATUS_UTIL_CONCURRENT_RWMUTEX_ERRORCHECK assert(holders_lk.lock()==true); assert(holders.count(thread::id())==0); #endif bool result; if (sec<1e-9) { result = pthread_rwlock_trywrlock(&lk)==0; } else { timespec end=to_timespec(get_clock_time()+sec); result = pthread_rwlock_timedwrlock(&lk, &end)==0; } #ifdef JUBATUS_UTIL_CONCURRENT_RWMUTEX_ERRORCHECK if (result) holders.insert(thread::id()); assert(holders_lk.unlock()==true); #endif return result; #else return false; #endif }
static void * th_fn(void *arg) { struct sigaction act; struct timespec abs_timeout; int rc = 0; handler_called = 0; /* Set up signal handler for SIGUSR1 */ act.sa_flags = 0; act.sa_handler = sig_handler; /* block all the signal when hanlding SIGUSR1 */ sigfillset(&act.sa_mask); sigaction(SIGUSR1, &act, 0); gettimeofday(&before_wait, NULL); abs_timeout.tv_sec = before_wait.tv_sec + TIMEOUT; abs_timeout.tv_nsec = before_wait.tv_usec * 1000; printf("thread: attempt timed write lock, %d seconds\n", TIMEOUT); thread_state = ENTERED_THREAD; rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); if (rc != ETIMEDOUT) { printf("sig_thread: pthread_rwlock_timedwrlock returns %d\n", rc); exit(PTS_FAIL); } printf("thread: timer correctly expired\n"); gettimeofday(&after_wait, NULL); thread_state = EXITING_THREAD; pthread_exit(0); return NULL; }
wod_ret_t wod_rwlock_wlock_timeout(wod_rwlock_t *rwlock,long long timeout) { struct timespec tm; tm.tv_sec = timeout/1000000; tm.tv_nsec = timeout-tm.tv_sec; return pthread_rwlock_timedwrlock(&rwlock->rw,&tm); }
void test_writer_timedwait(void) { fprintf(stderr, "test_writer_timedwait\n"); tell_thread_to_acquire_lock(READ_LOCK); struct timespec t = { 0, 0 }; int rc = pthread_rwlock_timedwrlock(&g_rwlock, &t); ASSERT_EQ(rc, ETIMEDOUT); tell_thread_to_release_lock(); }
static void *fn_wr(void *arg) { struct timespec timeout, ts; int rc; thread_state = ENTERED_THREAD; #ifdef CLOCK_REALTIME rc = clock_gettime(CLOCK_REALTIME, &ts); if (rc != 0) { perror("clock_gettime()"); exit(PTS_UNRESOLVED); } currsec1.tv_sec = ts.tv_sec; currsec1.tv_usec = ts.tv_nsec / 1000; #else gettimeofday(&currsec1, NULL); #endif /* Absolute time, not relative. */ timeout.tv_sec = currsec1.tv_sec + TIMEOUT; timeout.tv_nsec = currsec1.tv_usec * 1000; printf("thread: attempt timed write lock, %d secs\n", TIMEOUT); rc = pthread_rwlock_timedwrlock(&rwlock, &timeout); if (rc == ETIMEDOUT) { printf("thread: timer expired\n"); expired = 1; } else if (rc == 0) { printf("thread: acquired write lock\n"); expired = 0; printf("thread: unlock write lock\n"); if (pthread_rwlock_unlock(&rwlock) != 0) { printf("thread: error release write lock\n"); exit(PTS_UNRESOLVED); } } else { printf("thread: Error in pthread_rwlock_timedrdlock().\n"); exit(PTS_UNRESOLVED); } /* Get time after the mutex timed out in locking. */ #ifdef CLOCK_REALTIME rc = clock_gettime(CLOCK_REALTIME, &ts); if (rc != 0) { perror("clock_gettime()"); exit(PTS_UNRESOLVED); } currsec2.tv_sec = ts.tv_sec; currsec2.tv_usec = ts.tv_nsec / 1000; #else gettimeofday(&currsec2, NULL); #endif thread_state = EXITING_THREAD; pthread_exit(0); return NULL; }
static void * writer_thread (void *nr) { struct timespec ts; struct timespec delay; int n; delay.tv_sec = 0; delay.tv_nsec = DELAY; for (n = 0; n < WRITETRIES; ++n) { int e; do { struct timeval tv; (void) gettimeofday (&tv, NULL); TIMEVAL_TO_TIMESPEC (&tv, &ts); ts.tv_nsec += 2 * TIMEOUT; if (ts.tv_nsec >= 1000000000) { ts.tv_nsec -= 1000000000; ++ts.tv_sec; } printf ("writer thread %ld tries again\n", (long int) nr); e = pthread_rwlock_timedwrlock (&lock, &ts); if (e != 0 && e != ETIMEDOUT) { puts ("timedwrlock failed"); exit (1); } } while (e == ETIMEDOUT); printf ("writer thread %ld succeeded\n", (long int) nr); nanosleep (&delay, NULL); if (pthread_rwlock_unlock (&lock) != 0) { puts ("unlock for writer failed"); exit (1); } printf ("writer thread %ld released\n", (long int) nr); } return NULL; }
void *POSIX_Init( void *argument ) { int i; int status; pthread_t threadId; pthread_rwlockattr_t attr; TEST_BEGIN(); for ( i=0 ; i < OPERATION_COUNT - 1 ; i++ ) { status = pthread_create( &threadId, NULL, Middle, NULL ); rtems_test_assert( !status ); } status = pthread_create( &threadId, NULL, Low, NULL ); rtems_test_assert( !status ); /* * Timeout for 5 seconds from now. */ status = clock_gettime( CLOCK_REALTIME, &abstime ); rtems_test_assert( !status ); abstime.tv_sec += 5; /* * Deliberately create the rwlock after the threads. This way if the * threads do run before we intend, they will get an error. */ status = pthread_rwlockattr_init( &attr ); rtems_test_assert( status == 0 ); status = pthread_rwlock_init( &rwlock, &attr ); rtems_test_assert( status == 0 ); /* * Let the other threads start so the thread startup overhead, * is accounted for. When we return, we can start the benchmark. */ sched_yield(); /* let other threads run */ /* start the timer and switch through all the other tasks */ benchmark_timer_initialize(); /* write lock operation, this could be any write lock * I decided to use timedwrlock just to continue in the timed line */ status = pthread_rwlock_timedwrlock(&rwlock,0); rtems_test_assert( status == 0 ); return NULL; }
bool cRwLock::Lock(bool Write, int TimeoutMs) { int Result = 0; struct timespec abstime; if (TimeoutMs) { if (!GetAbsTime(&abstime, TimeoutMs)) TimeoutMs = 0; } if (Write) Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock); else Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock); return Result == 0; }
static int wr_timedlock(pthread_rwlock_t *lock, int timeout) { tv_t now; ts_t abs; int ret; tv_time(&now); tv_to_ts(&abs, &now); abs.tv_sec += timeout; ret = pthread_rwlock_timedwrlock(lock, &abs); return ret; }
/** * TimeWriteLock * @params[in] timeout * * This function will attempt to aquire a write lock. It will attempt to try for the timeout specific. * If it does aquire the lock true will be return. If the lock is not aquired false will be returned. * */ bool RWLock::TimeWriteLock(const struct timespec *timeout) { int ret = pthread_rwlock_timedwrlock(&m_lock, timeout); if (ret == 0) return true; switch(ret) { case ETIMEDOUT: return false; default: abort(); } return false; }
bool cThreadLockRw::TimedWriteLock( unsigned int timeout ) { struct timespec t; GetTimeout( t, timeout ); int rv = pthread_rwlock_timedwrlock( &m_rwlock, &t ); if ( rv ) { assert( rv == ETIMEDOUT ); return false; } return true; }
// WriteLock with absolute timeout bool RWLockImplPosix::writeLock(const ::icl_core::TimeStamp& timeout) { #ifdef _SYSTEM_DARWIN_ int ret = pthread_rwlock_trywrlock(m_rwlock); while ((ret != 0) && ((timeout > icl_core::TimeStamp::now()))) { // one microsecond icl_core::os::usleep(1); ret = pthread_rwlock_trywrlock(m_rwlock); } return (ret == 0); #else struct timespec timeout_timespec = timeout.timespec(); bool ret = pthread_rwlock_timedwrlock(m_rwlock, &timeout_timespec); return (ret == 0); #endif }
static void * th_fn(void *arg) { struct sigaction act; struct timespec abs_timeout; int rc; handler_state = 2; expired = 0; /* Set up handler for SIGUSR1 */ act.sa_flags = 0; act.sa_handler = sig_handler; /* block all the signal when hanlding SIGUSR1 */ sigfillset(&act.sa_mask); sigaction(SIGUSR1, &act, 0); gettimeofday(&before_wait, NULL); abs_timeout.tv_sec = before_wait.tv_sec + TIMEOUT; abs_timeout.tv_nsec = before_wait.tv_usec * 1000; thread_state = ENTERED_THREAD; printf("thread: attempt timed write lock, %d seconds\n", TIMEOUT); rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); if (rc == 0) { printf("thread: correctly acquired write lock\n"); expired = 0; } else if (rc == ETIMEDOUT) { printf("thread: timer expired, did not acquire write lock"); expired = 1; } else { printf("Error %d at pthread_rwlock_timedwrlock()\n", rc); exit(PTS_UNRESOLVED); } gettimeofday(&after_wait, NULL); thread_state = EXITING_THREAD; pthread_exit(0); return NULL; }
static void * writer (void *arg) { struct timespec ts; if (clock_gettime (CLOCK_REALTIME, &ts) != 0) { puts ("clock_gettime failed"); exit (EXIT_FAILURE); } ts.tv_sec += 1; int e = pthread_rwlock_timedwrlock (&r, &ts); if (e != ETIMEDOUT) { puts ("timedwrlock did not time out"); exit (EXIT_FAILURE); } return NULL; }
lagopus_result_t lagopus_rwlock_writer_timedlock(lagopus_rwlock_t *rwlptr, lagopus_chrono_t nsec) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; if (rwlptr != NULL && *rwlptr != NULL) { int st; if (nsec < 0) { if ((st = pthread_rwlock_wrlock(&((*rwlptr)->m_rwl))) == 0) { (*rwlptr)->m_prev_cancel_state = -INT_MAX; ret = LAGOPUS_RESULT_OK; } else { errno = st; ret = LAGOPUS_RESULT_POSIX_API_ERROR; } } else { struct timespec ts; lagopus_chrono_t now; WHAT_TIME_IS_IT_NOW_IN_NSEC(now); now += nsec; NSEC_TO_TS(now, ts); if ((st = pthread_rwlock_timedwrlock(&((*rwlptr)->m_rwl), &ts)) == 0) { (*rwlptr)->m_prev_cancel_state = -INT_MAX; ret = LAGOPUS_RESULT_OK; } else { errno = st; if (st == ETIMEDOUT) { ret = LAGOPUS_RESULT_TIMEDOUT; } else { ret = LAGOPUS_RESULT_POSIX_API_ERROR; } } } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
static void *fn_wr_1(void *arg) { thread_state = ENTERED_THREAD; struct timespec abs_timeout; int rc; pthread_rwlock_t rwlock; if (pthread_rwlock_init(&rwlock, NULL) != 0) { printf("thread1: Error at pthread_rwlock_init\n"); exit(PTS_UNRESOLVED); } currsec1 = time(NULL); /* Absolute time, not relative. */ abs_timeout.tv_sec = currsec1 + TIMEOUT; abs_timeout.tv_nsec = 0; printf("thread1: attempt timed lock for writing\n"); rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); if (rc == ETIMEDOUT) { printf("thread1: timer expired\n"); expired = 1; } else if (rc == 0) { printf("thread1: acquired write lock\n"); expired = 0; printf("thread1: unlock write lock\n"); if (pthread_rwlock_unlock(&rwlock) != 0) { printf("thread1: failed to release write lock\n"); exit(PTS_UNRESOLVED); } } else { printf("thread1: Error in pthread_rwlock_timedwrlock().\n"); exit(PTS_UNRESOLVED); } if (pthread_rwlock_destroy(&rwlock) != 0) { printf("thread1: Error at pthread_rwlockattr_destroy()"); exit(PTS_UNRESOLVED); } thread_state = EXITING_THREAD; pthread_exit(0); return NULL; }
LIB_EXPORT rc_t CC KRWLockTimedAcquireExcl ( KRWLock *self, timeout_t *tm ) { int status; if ( self == NULL ) return RC ( rcPS, rcRWLock, rcLocking, rcSelf, rcNull ); status = pthread_rwlock_trywrlock ( & self -> lock ); switch ( status ) { case 0: return 0; case EBUSY: if ( tm != NULL ) break; return RC ( rcPS, rcRWLock, rcLocking, rcLock, rcBusy ); case EINVAL: return RC ( rcPS, rcRWLock, rcLocking, rcRWLock, rcInvalid ); default: return RC ( rcPS, rcRWLock, rcLocking, rcNoObj, rcUnknown ); } if ( ! tm -> prepared ) TimeoutPrepare ( tm ); status = pthread_rwlock_timedwrlock ( & self -> lock, & tm -> ts ); switch ( status ) { case 0: break; case ETIMEDOUT: return RC ( rcPS, rcRWLock, rcLocking, rcTimeout, rcExhausted ); case EDEADLK: return RC ( rcPS, rcRWLock, rcLocking, rcThread, rcDeadlock ); case EINVAL: return RC ( rcPS, rcRWLock, rcLocking, rcTimeout, rcInvalid ); default: return RC ( rcPS, rcRWLock, rcLocking, rcNoObj, rcUnknown ); } return 0; }
int main() { pthread_t t; struct timespec abstime, reltime = { 1, 0 }; (void) pthread_win32_getabstime_np(&abstime, &reltime); assert(pthread_rwlock_timedwrlock(&rwlock1, &abstime) == 0); assert(pthread_create(&t, NULL, func, NULL) == 0); Sleep(2000); assert(pthread_rwlock_unlock(&rwlock1) == 0); assert(washere == 1); return 0; }
void * wrfunc(void * arg) { int result; result = pthread_rwlock_timedwrlock(&rwlock1, &abstime); if ((int) (size_t)arg == 1) { assert(result == 0); Sleep(2000); bankAccount += 10; assert(pthread_rwlock_unlock(&rwlock1) == 0); return ((void *)(size_t)bankAccount); } else if ((int) (size_t)arg == 2) { assert(result == ETIMEDOUT); return ((void *) 100); } return ((void *)(size_t)-1); }
bool ReadWriteLock::BeginWriteTimeout(long milliseconds) { #if defined(MEDUSA_ANDROID)||defined(MEDUSA_IOS) const int sleepMillis = 5; StopWatch watch; watch.Start(); do { RETURN_TRUE_IF_TRUE(TryBeginWrite()); Thread::Sleep(sleepMillis); watch.Shot(); } while (watch.ElapsedMilliseconds() < milliseconds); return false; #else struct timespec abstime = PerformanceCounter::ToAbsoluteTime(milliseconds); int result = pthread_rwlock_timedwrlock(&mLock, &abstime); return result == 0; #endif }
void *Middle( void *argument ) { int status; /* * Now we have finished the thread startup overhead, * so let other threads run. When we return, we can * finish the benchmark. */ sched_yield(); /* let other threads run */ /* This timed write lock operation will be blocked * because the other write operation has the lock */ status = pthread_rwlock_timedwrlock(&rwlock, &abstime); rtems_test_assert( status == 0 ); return NULL; }
DWORD VmDirRWLockWriteLock( PVMDIR_RWLOCK pLock, DWORD dwMilliSec ) { #ifdef __APPLE__ return VMDIR_ERROR_OPERATION_NOT_PERMITTED; #else DWORD dwError = 0; if (!pLock || !pLock->bInitialized) { dwError = VMDIR_ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } if (dwMilliSec) { struct timespec ts = {0}; uint64_t iTimeInMSec = 0; iTimeInMSec = dwMilliSec + VmDirGetTimeInMilliSec(); ts.tv_sec = iTimeInMSec / MSECS_PER_SEC; ts.tv_nsec = (iTimeInMSec % MSECS_PER_SEC) * NSECS_PER_MSEC; dwError = pthread_rwlock_timedwrlock(&pLock->lock, &ts); BAIL_ON_VMDIR_ERROR(dwError); } else { dwError = pthread_rwlock_wrlock(&pLock->lock); BAIL_ON_VMDIR_ERROR(dwError); } error: return dwError; #endif }
int __ast_rwlock_timedwrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout) { int res; #ifdef DEBUG_THREADS struct ast_lock_track *lt; int canlog = strcmp(filename, "logger.c") & t->tracking; #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { /* Don't warn abount uninitialized lock. * Simple try to initialize it. * May be not needed in linux system. */ res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", filename, line, func, name); return res; } } #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ if (t->tracking && !t->track) { ast_reentrancy_init(&t->track); } lt = t->track; if (t->tracking) { #ifdef HAVE_BKTR ast_reentrancy_lock(lt); if (lt->reentrancy != AST_MAX_REENTRANCY) { ast_bt_get_addresses(<->backtrace[lt->reentrancy]); bt = <->backtrace[lt->reentrancy]; } ast_reentrancy_unlock(lt); ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt); #else ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t); #endif } #endif /* DEBUG_THREADS */ #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout); #else do { struct timeval _start = ast_tvnow(), _diff; for (;;) { if (!(res = pthread_rwlock_trywrlock(&t->lock))) { break; } _diff = ast_tvsub(ast_tvnow(), _start); if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) { break; } usleep(1); } } while (0); #endif #ifdef DEBUG_THREADS if (!res && t->tracking) { ast_reentrancy_lock(lt); if (lt->reentrancy < AST_MAX_REENTRANCY) { lt->file[lt->reentrancy] = filename; lt->lineno[lt->reentrancy] = line; lt->func[lt->reentrancy] = func; lt->thread[lt->reentrancy] = pthread_self(); lt->reentrancy++; } ast_reentrancy_unlock(lt); if (t->tracking) { ast_mark_lock_acquired(t); } } else if (t->tracking) { #ifdef HAVE_BKTR if (lt->reentrancy) { ast_reentrancy_lock(lt); bt = <->backtrace[lt->reentrancy-1]; ast_reentrancy_unlock(lt); } else { bt = NULL; } if (t->tracking) { ast_remove_lock_info(t, bt); } #else if (t->tracking) { ast_remove_lock_info(t); } #endif } if (res) { __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n", filename, line, func, strerror(res)); DO_THREAD_CRASH; } #endif /* DEBUG_THREADS */ return res; }
DECL_FORCE_INLINE(int) rtSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies, PCRTLOCKVALSRCPOS pSrcPos) { /* * Validate input. */ struct RTSEMRWINTERNAL *pThis = hRWSem; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE); /* * Recursion? */ pthread_t Self = pthread_self(); pthread_t Writer; ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer); if (Writer == Self) { #ifdef RTSEMRW_STRICT int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorWrite, pSrcPos); if (RT_FAILURE(rc9)) return rc9; #endif Assert(pThis->cWrites < INT32_MAX); pThis->cWrites++; return VINF_SUCCESS; } /* * Try lock it. */ RTTHREAD hThreadSelf = NIL_RTTHREAD; if (cMillies) { #ifdef RTSEMRW_STRICT hThreadSelf = RTThreadSelfAutoAdopt(); int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true, cMillies, RTTHREADSTATE_RW_WRITE, true); if (RT_FAILURE(rc9)) return rc9; #else hThreadSelf = RTThreadSelf(); RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, true); #endif } if (cMillies == RT_INDEFINITE_WAIT) { /* take rwlock */ int rc = pthread_rwlock_wrlock(&pThis->RWLock); RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE); if (rc) { AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", hRWSem, rc)); return RTErrConvertFromErrno(rc); } } else { #ifdef RT_OS_DARWIN AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API.")); return VERR_NOT_IMPLEMENTED; #else /* !RT_OS_DARWIN */ /* * Get current time and calc end of wait time. */ struct timespec ts = {0,0}; clock_gettime(CLOCK_REALTIME, &ts); if (cMillies != 0) { ts.tv_nsec += (cMillies % 1000) * 1000000; ts.tv_sec += cMillies / 1000; if (ts.tv_nsec >= 1000000000) { ts.tv_nsec -= 1000000000; ts.tv_sec++; } } /* take rwlock */ int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts); RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE); if (rc) { AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", hRWSem, rc)); return RTErrConvertFromErrno(rc); } #endif /* !RT_OS_DARWIN */ } ATOMIC_SET_PTHREAD_T(&pThis->Writer, Self); pThis->cWrites = 1; Assert(!pThis->cReaders); #ifdef RTSEMRW_STRICT RTLockValidatorRecExclSetOwner(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true); #endif return VINF_SUCCESS; }