Browse Source

Merge 8a88b2aa67 into 6af0909e1d

pull/412/merge
Max Tomago GitHub 3 years ago
parent
commit
925ff3399c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 227 additions and 71 deletions
  1. +3
    -0
      common/wscript
  2. +50
    -0
      posix/JackPosixCommon.cpp
  3. +30
    -0
      posix/JackPosixCommon.h
  4. +76
    -54
      posix/JackPosixProcessSync.cpp
  5. +0
    -1
      posix/JackPosixProcessSync.h
  6. +68
    -16
      posix/JackPosixSemaphore.cpp

+ 3
- 0
common/wscript View File

@@ -83,6 +83,7 @@ def build(bld):
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c', 'promiscuous.c',
'../posix/JackPosixCommon.cpp',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixMutex.cpp', '../posix/JackPosixMutex.cpp',
@@ -113,6 +114,7 @@ def build(bld):
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c', 'promiscuous.c',
'../posix/JackPosixCommon.cpp',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackFifo.cpp', '../posix/JackFifo.cpp',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
@@ -128,6 +130,7 @@ def build(bld):
'JackDebugClient.cpp', 'JackDebugClient.cpp',
'timestamps.c', 'timestamps.c',
'promiscuous.c', 'promiscuous.c',
'../posix/JackPosixCommon.cpp',
'../posix/JackPosixProcessSync.cpp', '../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixThread.cpp', '../posix/JackPosixThread.cpp',
'../posix/JackPosixMutex.cpp', '../posix/JackPosixMutex.cpp',


+ 50
- 0
posix/JackPosixCommon.cpp View File

@@ -0,0 +1,50 @@
#include "JackPosixCommon.h"
#include "JackConstants.h"
#include "JackTools.h"
#include "JackError.h"
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

namespace Jack
{

void JackPosixTools::TimespecAdd(const struct timespec *left,
const struct timespec *right, struct timespec *result)
{
assert(result != NULL);
result->tv_sec = left->tv_sec + right->tv_sec;
result->tv_nsec = left->tv_nsec + right->tv_nsec;
if (result->tv_nsec >= 1000000000) {
result->tv_nsec -= 1000000000;
result->tv_sec += 1;
}
}

void JackPosixTools::TimespecSub(const struct timespec *left,
const struct timespec *right, struct timespec *result)
{
assert(result != NULL);
result->tv_sec = left->tv_sec - right->tv_sec;
result->tv_nsec = left->tv_nsec - right->tv_nsec;
if (result->tv_nsec < 0) {
result->tv_nsec += 1000000000;
result->tv_sec -= 1;
}
}

int JackPosixTools::TimespecCmp(const struct timespec *left,
const struct timespec *right)
{
if (left->tv_sec != right->tv_sec)
return left->tv_sec < right->tv_sec ? -1 : 1;
if (left->tv_nsec != right->tv_nsec)
return left->tv_nsec < right->tv_nsec ? -1 : 1;
return 0;
}

} // end of namespace



+ 30
- 0
posix/JackPosixCommon.h View File

@@ -0,0 +1,30 @@
#ifndef __JackPosixCommon__
#define __JackPosixCommon__

#include "jslist.h"
#include "JackCompilerDeps.h"
#include "JackError.h"

#include <errno.h>
#include <time.h>
#include <unistd.h>

namespace Jack
{

struct SERVER_EXPORT JackPosixTools
{
static void TimespecAdd(const struct timespec *left,
const struct timespec *right, struct timespec *result);

static void TimespecSub(const struct timespec *left,
const struct timespec *right, struct timespec *result);

static int TimespecCmp(const struct timespec *left,
const struct timespec *right);
};

} // end of namespace

#endif


+ 76
- 54
posix/JackPosixProcessSync.cpp View File

@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


#include "JackPosixProcessSync.h" #include "JackPosixProcessSync.h"
#include "JackError.h" #include "JackError.h"
#include "JackPosixCommon.h"


namespace Jack namespace Jack
{ {
@@ -103,73 +104,94 @@ void JackPosixProcessSync::LockedWait()
} }
} }


bool JackPosixProcessSync::TimedWait(long usec)
{
ThrowIf(!pthread_equal(pthread_self(), fOwner), JackException("JackPosixProcessSync::TimedWait: a thread has to have locked a mutex before it can wait"));
fOwner = 0;

struct timeval T0, T1;
timespec time;
struct timeval now;
int res;

jack_log("JackPosixProcessSync::TimedWait time out = %ld", usec);
gettimeofday(&T0, 0);

gettimeofday(&now, 0);
unsigned int next_date_usec = now.tv_usec + usec;
time.tv_sec = now.tv_sec + (next_date_usec / 1000000);
time.tv_nsec = (next_date_usec % 1000000) * 1000;

res = pthread_cond_timedwait(&fCond, &fMutex, &time);
if (res != 0) {
jack_error("JackPosixProcessSync::TimedWait error usec = %ld err = %s", usec, strerror(res));
} else {
fOwner = pthread_self();
}

gettimeofday(&T1, 0);
jack_log("JackPosixProcessSync::TimedWait finished delta = %5.1lf",
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec));

return (res == 0);
}

// TO DO : check thread consistency? // TO DO : check thread consistency?
bool JackPosixProcessSync::LockedTimedWait(long usec) bool JackPosixProcessSync::LockedTimedWait(long usec)
{ {
struct timeval T0, T1;
timespec time;
struct timeval now;
int res1, res2;
int res1, res2, res3;
struct timespec rel_timeout, now_mono, end_mono, now_real, end_real;
struct timespec diff_mono, final_time;
int old_errno;
bool mono_available = true;
double delta;


res1 = pthread_mutex_lock(&fMutex); res1 = pthread_mutex_lock(&fMutex);
if (res1 != 0) { if (res1 != 0) {
jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1));
}

jack_log("JackPosixProcessSync::TimedWait time out = %ld", usec);
gettimeofday(&T0, 0);

gettimeofday(&now, 0);
unsigned int next_date_usec = now.tv_usec + usec;
time.tv_sec = now.tv_sec + (next_date_usec / 1000000);
time.tv_nsec = (next_date_usec % 1000000) * 1000;
res2 = pthread_cond_timedwait(&fCond, &fMutex, &time);
if (res2 != 0) {
jack_error("JackPosixProcessSync::LockedTimedWait error usec = %ld err = %s", usec, strerror(res2));
jack_error("JackPosixProcessSync::LockedTimedWait error err = %s",
usec, strerror(res1));
}

jack_log("JackPosixProcessSync::LockedTimedWait time out = %ld", usec);
/* Convert usec argument to timespec */
rel_timeout.tv_sec = usec / 1000000;
rel_timeout.tv_nsec = (usec % 1000000) * 1000;

/* Calculate absolute monotonic timeout */
res3 = clock_gettime(CLOCK_MONOTONIC, &now_mono);
if (res3 != 0) {
mono_available = false;
}
JackPosixTools::TimespecAdd(&now_mono, &rel_timeout, &end_mono);

/* pthread_cond_timedwait() is affected by abrupt time jumps, i.e. when the
* system time is changed. To protect against this, measure the time
* difference between and after the sem_timedwait() call and if it suggests
* that there has been a time jump, restart the call. */
if (mono_available) {
for (;;) {
/* Calculate absolute realtime timeout, assuming no steps */
res3 = clock_gettime(CLOCK_REALTIME, &now_real);
assert(res3 == 0);
JackPosixTools::TimespecSub(&end_mono, &now_mono, &diff_mono);
JackPosixTools::TimespecAdd(&now_real, &diff_mono, &end_real);

res2 = pthread_cond_timedwait(&fCond, &fMutex, &end_real);
if (res2 != ETIMEDOUT) {
break;
}

/* Compare with monotonic timeout, in case a step happened */
old_errno = errno;
res3 = clock_gettime(CLOCK_MONOTONIC, &now_mono);
assert(res3 == 0);
errno = old_errno;
if (JackPosixTools::TimespecCmp(&now_mono, &end_mono) >= 0) {
break;
}
}
} else {
/* CLOCK_MONOTONIC is not supported, do not check for time skips. */
res3 = clock_gettime(CLOCK_REALTIME, &now_real);
assert(res3 == 0);
JackPosixTools::TimespecAdd(&now_real, &rel_timeout, &end_real);
res2 = pthread_cond_timedwait(&fCond, &fMutex, &end_real);
} }


gettimeofday(&T1, 0);
res1 = pthread_mutex_unlock(&fMutex); res1 = pthread_mutex_unlock(&fMutex);
if (res1 != 0) { if (res1 != 0) {
jack_error("JackPosixProcessSync::LockedTimedWait error err = %s", usec, strerror(res1));
jack_error("JackPosixProcessSync::LockedTimedWait error err = %s",
strerror(res1));
} }


jack_log("JackPosixProcessSync::TimedWait finished delta = %5.1lf",
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec));
if (res2 != 0) {
jack_error("JackPosixProcessSync::LockedTimedWait error usec = %ld err = %s",
usec, strerror(res2));
}


return (res2 == 0);
old_errno = errno;
if (mono_available) {
res3 = clock_gettime(CLOCK_MONOTONIC, &final_time);
assert(res3 == 0);
delta = 1e6 * final_time.tv_sec - 1e6 * now_mono.tv_sec +
(final_time.tv_nsec - now_mono.tv_nsec) / 1000;
} else {
res3 = clock_gettime(CLOCK_REALTIME, &final_time);
assert(res3 == 0);
delta = 1e6 * final_time.tv_sec - 1e6 * now_real.tv_sec +
(final_time.tv_nsec - now_real.tv_nsec) / 1000;
}
errno = old_errno;
jack_log("JackPosixProcessSync::LockedTimedWait finished delta = %5.1lf", delta);
return res2 == 0;
} }






+ 0
- 1
posix/JackPosixProcessSync.h View File

@@ -52,7 +52,6 @@ class JackPosixProcessSync : public JackBasePosixMutex
pthread_cond_destroy(&fCond); pthread_cond_destroy(&fCond);
} }


bool TimedWait(long usec);
bool LockedTimedWait(long usec); bool LockedTimedWait(long usec);


void Wait(); void Wait();


+ 68
- 16
posix/JackPosixSemaphore.cpp View File

@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackTools.h" #include "JackTools.h"
#include "JackConstants.h" #include "JackConstants.h"
#include "JackError.h" #include "JackError.h"
#include "JackPosixCommon.h"
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
@@ -122,29 +123,80 @@ bool JackPosixSemaphore::Wait()


bool JackPosixSemaphore::TimedWait(long usec) bool JackPosixSemaphore::TimedWait(long usec)
{ {
int res;
struct timeval now;
timespec time;
int res;
struct timespec rel_timeout, now_mono, end_mono, now_real, end_real;
struct timespec diff_mono;


if (!fSemaphore) { if (!fSemaphore) {
jack_error("JackPosixSemaphore::TimedWait name = %s already deallocated!!", fName); jack_error("JackPosixSemaphore::TimedWait name = %s already deallocated!!", fName);
return false; return false;
} }
gettimeofday(&now, 0);
time.tv_sec = now.tv_sec + usec / 1000000;
long tv_usec = (now.tv_usec + (usec % 1000000));
time.tv_sec += tv_usec / 1000000;
time.tv_nsec = (tv_usec % 1000000) * 1000;

while ((res = sem_timedwait(fSemaphore, &time)) < 0) {
jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno));
jack_log("JackPosixSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
jack_log("JackPosixSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
if (errno != EINTR) {
break;

/* Convert usec argument to timespec */
rel_timeout.tv_sec = usec / 1000000;
rel_timeout.tv_nsec = (usec % 1000000) * 1000;

/* Calculate absolute monotonic timeout */
res = clock_gettime(CLOCK_MONOTONIC, &now_mono);
if (res != 0) {
/* CLOCK_MONOTONIC is not supported, do not check for time skips. */
res = clock_gettime(CLOCK_REALTIME, &now_real);
assert(res == 0);
JackPosixTools::TimespecAdd(&now_real, &rel_timeout, &end_real);
while ((res = sem_timedwait(fSemaphore, &end_real)) < 0) {
if (errno != EINTR) {
break;
}
}
if (res == 0) {
return true;
} else {
goto err;
} }
} }
return (res == 0);
JackPosixTools::TimespecAdd(&now_mono, &rel_timeout, &end_mono);

/* sem_timedwait() is affected by abrupt time jumps, i.e. when the system
* time is changed. To protect against this, measure the time difference
* between and after the sem_timedwait() call and if it suggests that there
* has been a time jump, restart the call. */
for (;;) {
/* Calculate absolute realtime timeout, assuming no steps */
res = clock_gettime(CLOCK_REALTIME, &now_real);
assert(res == 0);
JackPosixTools::TimespecSub(&end_mono, &now_mono, &diff_mono);
JackPosixTools::TimespecAdd(&now_real, &diff_mono, &end_real);

while ((res = sem_timedwait(fSemaphore, &end_real)) < 0) {
if (errno != EINTR) {
break;
}
}
if (res == 0) {
return true;
}
if (errno != ETIMEDOUT) {
goto err;
}

/* Compare with monotonic timeout, in case a step happened */
int old_errno = errno;
res = clock_gettime(CLOCK_MONOTONIC, &now_mono);
assert(res == 0);
errno = old_errno;
if (JackPosixTools::TimespecCmp(&now_mono, &end_mono) >= 0) {
goto err;
}
}
return true;

err:
jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno));
jack_log("JackPosixSemaphore::TimedWait now : %ld %ld ", now_real.tv_sec,
now_real.tv_nsec / 1000);
jack_log("JackPosixSemaphore::TimedWait next : %ld %ld ", end_real.tv_sec,
end_real.tv_nsec / 1000);
return false;
} }


// Server side : publish the semaphore in the global namespace // Server side : publish the semaphore in the global namespace


Loading…
Cancel
Save