OpenZFS 6739 - assumption in cv_timedwait_hires

Userland version of cv_timedwait_hires() always assumes absolute time.

Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Ported by: Denys Rtveliashvili <denys@rtveliashvili.name>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/6739
OpenZFS-commit: https://github.com/illumos/illumos-gate/commit/41c6413

Porting Notes:
The ported change has revealed a number of problems in the Linux-specific code,
as it was expecting incorrect return codes from pthread_* functions.
Reviewed and improved the usage of pthread_* function in lib/libzpool/kernel.c.
This commit is contained in:
Denys Rtveliashvili 2016-05-15 22:18:25 +00:00 committed by Brian Behlendorf
parent dabe1c42f9
commit 206971d234
2 changed files with 26 additions and 27 deletions

View File

@ -25,7 +25,7 @@
/* /*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved. * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
*/ */
#ifndef _SYS_ZFS_CONTEXT_H #ifndef _SYS_ZFS_CONTEXT_H
@ -353,6 +353,7 @@ typedef struct kcondvar {
} kcondvar_t; } kcondvar_t;
#define CV_DEFAULT 0 #define CV_DEFAULT 0
#define CALLOUT_FLAG_ABSOLUTE 0x2
extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg); extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg);
extern void cv_destroy(kcondvar_t *cv); extern void cv_destroy(kcondvar_t *cv);

View File

@ -104,8 +104,7 @@ thread_fini(void)
kthread_nr--; /* Main thread is exiting */ kthread_nr--; /* Main thread is exiting */
while (kthread_nr > 0) while (kthread_nr > 0)
VERIFY3S(pthread_cond_wait(&kthread_cond, &kthread_lock), ==, VERIFY0(pthread_cond_wait(&kthread_cond, &kthread_lock));
0);
ASSERT3S(kthread_nr, ==, 0); ASSERT3S(kthread_nr, ==, 0);
VERIFY3S(pthread_mutex_unlock(&kthread_lock), ==, 0); VERIFY3S(pthread_mutex_unlock(&kthread_lock), ==, 0);
@ -181,6 +180,10 @@ zk_thread_create(caddr_t stk, size_t stksize, thread_func_t func, void *arg,
VERIFY3S(stksize, >, 0); VERIFY3S(stksize, >, 0);
stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE); stksize = P2ROUNDUP(MAX(stksize, TS_STACK_MIN), PAGESIZE);
/*
* If this ever fails, it may be because the stack size is not a
* multiple of system page size.
*/
VERIFY0(pthread_attr_setstacksize(&attr, stksize)); VERIFY0(pthread_attr_setstacksize(&attr, stksize));
VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE)); VERIFY0(pthread_attr_setguardsize(&attr, PAGESIZE));
@ -199,11 +202,11 @@ zk_thread_exit(void)
umem_free(kt, sizeof (kthread_t)); umem_free(kt, sizeof (kthread_t));
pthread_mutex_lock(&kthread_lock); VERIFY0(pthread_mutex_lock(&kthread_lock));
kthread_nr--; kthread_nr--;
pthread_mutex_unlock(&kthread_lock); VERIFY0(pthread_mutex_unlock(&kthread_lock));
pthread_cond_broadcast(&kthread_cond); VERIFY0(pthread_cond_broadcast(&kthread_cond));
pthread_exit((void *)TS_MAGIC); pthread_exit((void *)TS_MAGIC);
} }
@ -316,13 +319,15 @@ mutex_enter(kmutex_t *mp)
int int
mutex_tryenter(kmutex_t *mp) mutex_tryenter(kmutex_t *mp)
{ {
int err;
ASSERT3U(mp->m_magic, ==, MTX_MAGIC); ASSERT3U(mp->m_magic, ==, MTX_MAGIC);
ASSERT3P(mp->m_owner, !=, MTX_DEST); ASSERT3P(mp->m_owner, !=, MTX_DEST);
if (0 == pthread_mutex_trylock(&mp->m_lock)) { if (0 == (err = pthread_mutex_trylock(&mp->m_lock))) {
ASSERT3P(mp->m_owner, ==, MTX_INIT); ASSERT3P(mp->m_owner, ==, MTX_INIT);
mp->m_owner = curthread; mp->m_owner = curthread;
return (1); return (1);
} else { } else {
VERIFY3S(err, ==, EBUSY);
return (0); return (0);
} }
} }
@ -464,14 +469,14 @@ cv_init(kcondvar_t *cv, char *name, int type, void *arg)
{ {
ASSERT3S(type, ==, CV_DEFAULT); ASSERT3S(type, ==, CV_DEFAULT);
cv->cv_magic = CV_MAGIC; cv->cv_magic = CV_MAGIC;
VERIFY3S(pthread_cond_init(&cv->cv, NULL), ==, 0); VERIFY0(pthread_cond_init(&cv->cv, NULL));
} }
void void
cv_destroy(kcondvar_t *cv) cv_destroy(kcondvar_t *cv)
{ {
ASSERT3U(cv->cv_magic, ==, CV_MAGIC); ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
VERIFY3S(pthread_cond_destroy(&cv->cv), ==, 0); VERIFY0(pthread_cond_destroy(&cv->cv));
cv->cv_magic = 0; cv->cv_magic = 0;
} }
@ -481,9 +486,7 @@ cv_wait(kcondvar_t *cv, kmutex_t *mp)
ASSERT3U(cv->cv_magic, ==, CV_MAGIC); ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
ASSERT3P(mutex_owner(mp), ==, curthread); ASSERT3P(mutex_owner(mp), ==, curthread);
mp->m_owner = MTX_INIT; mp->m_owner = MTX_INIT;
int ret = pthread_cond_wait(&cv->cv, &mp->m_lock); VERIFY0(pthread_cond_wait(&cv->cv, &mp->m_lock));
if (ret != 0)
VERIFY3S(ret, ==, EINTR);
mp->m_owner = curthread; mp->m_owner = curthread;
} }
@ -497,7 +500,6 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
ASSERT3U(cv->cv_magic, ==, CV_MAGIC); ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
top:
delta = abstime - ddi_get_lbolt(); delta = abstime - ddi_get_lbolt();
if (delta <= 0) if (delta <= 0)
return (-1); return (-1);
@ -519,10 +521,7 @@ top:
if (error == ETIMEDOUT) if (error == ETIMEDOUT)
return (-1); return (-1);
if (error == EINTR) VERIFY0(error);
goto top;
VERIFY3S(error, ==, 0);
return (1); return (1);
} }
@ -536,10 +535,12 @@ cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
timestruc_t ts; timestruc_t ts;
hrtime_t delta; hrtime_t delta;
ASSERT(flag == 0); ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
delta = tim;
if (flag & CALLOUT_FLAG_ABSOLUTE)
delta -= gethrtime();
top:
delta = tim - gethrtime();
if (delta <= 0) if (delta <= 0)
return (-1); return (-1);
@ -551,13 +552,10 @@ top:
error = pthread_cond_timedwait(&cv->cv, &mp->m_lock, &ts); error = pthread_cond_timedwait(&cv->cv, &mp->m_lock, &ts);
mp->m_owner = curthread; mp->m_owner = curthread;
if (error == ETIME) if (error == ETIMEDOUT)
return (-1); return (-1);
if (error == EINTR) VERIFY0(error);
goto top;
ASSERT(error == 0);
return (1); return (1);
} }
@ -566,14 +564,14 @@ void
cv_signal(kcondvar_t *cv) cv_signal(kcondvar_t *cv)
{ {
ASSERT3U(cv->cv_magic, ==, CV_MAGIC); ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
VERIFY3S(pthread_cond_signal(&cv->cv), ==, 0); VERIFY0(pthread_cond_signal(&cv->cv));
} }
void void
cv_broadcast(kcondvar_t *cv) cv_broadcast(kcondvar_t *cv)
{ {
ASSERT3U(cv->cv_magic, ==, CV_MAGIC); ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
VERIFY3S(pthread_cond_broadcast(&cv->cv), ==, 0); VERIFY0(pthread_cond_broadcast(&cv->cv));
} }
/* /*