Browse Source

reworked config headers etc; rework clockfix patch; exit if -R requested but unobtainable

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@948 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
pbd 20 years ago
parent
commit
7e8cf3c23c
38 changed files with 477 additions and 553 deletions
  1. +1
    -1
      Makefile.am
  2. +1
    -3
      config/Makefile.am
  3. +14
    -18
      config/configure.host
  4. +3
    -5
      config/cpu/generic/cycles.h
  5. +7
    -31
      config/cpu/i386/atomicity.h
  6. +12
    -2
      config/cpu/i386/cycles.h
  7. +0
    -54
      config/cpu/i486/atomicity.h
  8. +2
    -53
      config/cpu/i486/cycles.h
  9. +2
    -40
      config/os/generic/time.h
  10. +5
    -65
      config/os/gnu-linux/time.h
  11. +0
    -161
      config/os/macosx/fakepoll.h
  12. +156
    -23
      config/os/macosx/poll.h
  13. +0
    -28
      config/os/macosx/portaudio.h
  14. +2
    -19
      config/os/macosx/time.h
  15. +0
    -23
      config/sysdeps/Makefile.am
  16. +24
    -0
      config/sysdeps/atomicity.h
  17. +28
    -0
      config/sysdeps/cycles.h
  18. +8
    -0
      config/sysdeps/getopt.h
  19. +10
    -0
      config/sysdeps/ipc.h
  20. +8
    -0
      config/sysdeps/mach_port.h
  21. +8
    -0
      config/sysdeps/pThreadUtilities.h
  22. +14
    -0
      config/sysdeps/poll.h
  23. +8
    -0
      config/sysdeps/portaudio.h
  24. +12
    -0
      config/sysdeps/time.c
  25. +12
    -0
      config/sysdeps/time.h
  26. +52
    -8
      configure.ac
  27. +2
    -2
      example-clients/Makefile.am
  28. +2
    -1
      example-clients/metro.c
  29. +2
    -0
      jack/engine.h
  30. +12
    -0
      jack/internal.h
  31. +4
    -0
      jack/thread.h
  32. +31
    -11
      jackd/engine.c
  33. +3
    -0
      jackd/jackd.1.in
  34. +17
    -1
      jackd/jackd.c
  35. +2
    -1
      libjack/Makefile.am
  36. +4
    -2
      libjack/client.c
  37. +3
    -1
      libjack/local.h
  38. +6
    -0
      libjack/thread.c

+ 1
- 1
Makefile.am View File

@@ -13,7 +13,7 @@ dist-check-doxygen:
@false
endif

SUBDIRS = config jack libjack jackd drivers example-clients $(DOC_DIR)
SUBDIRS = jack libjack jackd drivers example-clients $(DOC_DIR)
DIST_SUBDIRS = config jack libjack jackd drivers example-clients doc

pkgconfigdir = $(libdir)/pkgconfig


+ 1
- 3
config/Makefile.am View File

@@ -3,9 +3,7 @@
# this is sufficient. Unfortunately, their CVS subdirectories also
# get distributed as a side-effect.

EXTRA_DIST = configure.host depcomp cpu os
EXTRA_DIST = configure.host depcomp cpu os sysdeps
MAINTAINERCLEANFILES = Makefile.in config.guess config.sub \
install-sh ltmain.sh missing mkinstalldirs

SUBDIRS = sysdeps
DIST_SUBDIRS = sysdeps

+ 14
- 18
config/configure.host View File

@@ -109,12 +109,8 @@ case "${host_cpu}" in
;;
esac

# Now look for the file(s) usually tied to a CPU model, and make
# default choices for those if they haven't been explicitly set
# already.
cpu_include_dir="cpu/${try_cpu}"
atomicity_include_dir=$cpu_include_dir

# set the CPU that will be used to select atomicity functionality
ATOMICITY_TARGET=${try_cpu}

# Set any OS-dependent bits.
# Set the os_include_dir.
@@ -126,33 +122,33 @@ case "${host_os}" in
# We set os_include_dir to os/aix only on AIX 4.3 and newer, but
# os/aix/atomicity.h works on earlier versions of AIX 4.*, so we
# explicitly duplicate the directory for 4.[<3].
os_include_dir="os/aix"
atomicity_include_dir="os/aix"
OSPLATFORM="AIX"
ATOMICITY_TARGET="AIX"
OS_LDFLAGS="-Wl,-G"
;;
aix4.*)
os_include_dir="os/generic"
atomicity_include_dir="os/aix"
OSPLATFORM="GENERIC"
ATOMICITY_TARGET="AIX"
;;
aix*)
os_include_dir="os/generic"
atomicity_include_dir="cpu/generic"
OSPLATFORM="GENERIC"
ATOMICITY_TARGET="GENERIC"
;;
gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu)
os_include_dir="os/gnu-linux"
OSPLATFORM="GNULINUX"
;;
freebsd*)
# current FreeBSD header files conflict with the OSS driver's
# barrier code, this may be fixed in 5.3, stay tuned.
os_include_dir="os/generic"
OSPLATFORM="GENERIC"
USE_BARRIER="no"
;;
irix*)
os_include_dir="os/irix"
atomicity_include_dir=$os_include_dir
OSPLATFORM="IRIX"
ATOMICITY_TARGET="IRIX"
;;
darwin*)
os_include_dir="os/macosx"
OSPLATFORM="MACOSX"
JACK_THREAD_STACK_TOUCH=10000 # need small realtime stack
JACK_CPP_VARARGS_BROKEN=1
JACK_DO_NOT_MLOCK=1
@@ -161,7 +157,7 @@ case "${host_os}" in
TRY_POSIX_SHM=yes # POSIX shm works better
;;
*)
os_include_dir="os/generic"
OSPLATFORM="GENERIC"
;;
esac



+ 3
- 5
config/cpu/generic/cycles.h View File

@@ -1,6 +1,5 @@
/*
Copyright (C) 2001 Paul Davis
Code derived from various headers from the Linux kernel
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,20 +21,19 @@
#ifndef __jack_cycles_h__
#define __jack_cycles_h__

/* generic solution */
/* generic solution that is not really a solution at all */

#warning You are compiling JACK on a platform for which jack/cycles.h needs work
#warning You are compiling JACK on a platform for which jack/config/sysdep/cycles.h needs work
#include <sys/time.h>

typedef long cycles_t;
extern cycles_t cacheflush_time;

static inline cycles_t get_cycles(void)
{
struct timeval tv;
gettimeofday (&tv, NULL);

return tv.tv_usec;
return ((cycles_t) tv.tv_sec * 1000000) + tv.tv_usec;
}

#endif /* __jack_cycles_h__ */

+ 7
- 31
config/cpu/i386/atomicity.h View File

@@ -1,6 +1,4 @@
// Low-level functions for atomic operations: x86, x >= 3 version -*- C++ -*-

// Copyright (C) 2003 Free Software Foundation, Inc.
// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -32,37 +30,14 @@

typedef int _Atomic_word;

template<int __inst>
struct __Atomicity_lock
{
static volatile _Atomic_word _S_atomicity_lock;
};

template<int __inst>
volatile _Atomic_word __Atomicity_lock<__inst>::_S_atomicity_lock = 0;

template volatile _Atomic_word __Atomicity_lock<0>::_S_atomicity_lock;

static inline _Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
register _Atomic_word __result, __tmp = 1;

/* obtain the atomic exchange/add spin lock */
do {
__asm__ __volatile__ ("xchg{l} {%0,%1|%1,%0}"
: "=m" (__Atomicity_lock<0>::_S_atomicity_lock),
"+r" (__tmp)
: "m" (__Atomicity_lock<0>::_S_atomicity_lock));
} while (__tmp);

__result = *__mem;
*__mem += __val;

/* release spin lock */
__Atomicity_lock<0>::_S_atomicity_lock = 0;

register _Atomic_word __result;
__asm__ __volatile__ ("lock; xaddl %0,%1"
: "=r" (__result), "=m" (*__mem)
: "0" (__val), "m" (*__mem));
return __result;
}

@@ -70,7 +45,8 @@ static inline void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
__exchange_and_add(__mem, __val);
__asm__ __volatile__ ("lock; addl %1,%0"
: "=m" (*__mem) : "ir" (__val), "m" (*__mem));
}

#endif /* atomicity.h */

+ 12
- 2
config/cpu/i386/cycles.h View File

@@ -19,6 +19,16 @@
$Id$
*/

/* the i486 version of this header is compatible */
#ifndef __jack_cycles_h__
#define __jack_cycles_h__

#include <config/cpu/i486/cycles.h>
typedef unsigned long long cycles_t;

static inline cycles_t get_cycles (void)
{
unsigned long long ret;
__asm__ __volatile__("rdtsc" : "=A" (ret));
return ret;
}

#endif /* __jack_cycles_h__ */

+ 0
- 54
config/cpu/i486/atomicity.h View File

@@ -1,54 +0,0 @@
// Low-level functions for atomic operations: x86, x >= 4 version -*- C++ -*-

// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

#ifndef _GLIBCXX_ATOMICITY_H
#define _GLIBCXX_ATOMICITY_H 1

typedef int _Atomic_word;

static inline _Atomic_word
__attribute__ ((__unused__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
{
register _Atomic_word __result;
__asm__ __volatile__ ("lock; xaddl %0,%1"
: "=r" (__result), "=m" (*__mem)
: "0" (__val), "m" (*__mem));
return __result;
}

static inline void
__attribute__ ((__unused__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{
__asm__ __volatile__ ("lock; addl %1,%0"
: "=m" (*__mem) : "ir" (__val), "m" (*__mem));
}

#endif /* atomicity.h */

+ 2
- 53
config/cpu/i486/cycles.h View File

@@ -1,54 +1,3 @@
/*
Copyright (C) 2001 Paul Davis
Code derived from various headers from the Linux kernel
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
/* the i386 version of this header is compatible */

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

$Id$
*/

#ifndef __jack_cycles_h__
#define __jack_cycles_h__

/*
* Standard way to access the cycle counter on i586+ CPUs.
* Currently only used on SMP.
*
* If you really have a SMP machine with i486 chips or older,
* compile for that, and this will just always return zero.
* That's ok, it just means that the nicer scheduling heuristics
* won't work for you.
*
* We only use the low 32 bits, and we'd simply better make sure
* that we reschedule before that wraps. Scheduling at least every
* four billion cycles just basically sounds like a good idea,
* regardless of how fast the machine is.
*/
typedef unsigned long long cycles_t;

extern cycles_t cacheflush_time;

#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))

static inline cycles_t get_cycles (void)
{
unsigned long long ret;

rdtscll(ret);
return ret;
}

#endif /* __jack_cycles_h__ */
#include <config/cpu/i386/cycles.h>

+ 2
- 40
config/os/generic/time.h View File

@@ -22,49 +22,11 @@
#ifndef __jack_time_h__
#define __jack_time_h__

#include <stdio.h>
#include <jack/internal.h>
#include <sysdeps/cycles.h>

/* This is a kludge. We need one global instantiation of this
* variable in each address space. So, libjack/client.c declares the
* actual storage. Other source files will see it as an extern. */
#define JACK_TIME_GLOBAL_DECL jack_time_t __jack_cpu_mhz
extern JACK_TIME_GLOBAL_DECL;

static inline jack_time_t
inline jack_time_t
jack_get_microseconds (void) {
return get_cycles() / __jack_cpu_mhz;
}

/* This function is inspired by similar code in MPLayer.
* It should be quite portable
*/
static inline jack_time_t
jack_get_mhz (void)
{
jack_time_t tsc_start, tsc_end;
struct timeval tv_start, tv_end;
long usec_delay;
jack_time_t mhz;
tsc_start = get_cycles();
gettimeofday(&tv_start, NULL);
usleep(100000);
tsc_end = get_cycles();
gettimeofday(&tv_end, NULL);
usec_delay = 1000000 * (tv_end.tv_sec - tv_start.tv_sec)
+ (tv_end.tv_usec - tv_start.tv_usec);
mhz = (tsc_end - tsc_start) / usec_delay;
return mhz;
}

/* This should only be called ONCE per process. */
static inline void
jack_init_time ()
{
__jack_cpu_mhz = jack_get_mhz ();
return jack_get_microseconds_from_system ();
}

#endif /* __jack_time_h__ */

+ 5
- 65
config/os/gnu-linux/time.h View File

@@ -1,5 +1,6 @@
/*
Copyright (C) 2001-2003 Paul Davis
Copyright (C) 2005 Jussi Laako

This is the GNU/Linux version.
@@ -19,79 +20,18 @@

$Id$
*/

#ifndef __jack_time_h__
#define __jack_time_h__

#include <stdio.h>
#include <jack/internal.h>
#include <sysdeps/cycles.h>

/* This is a kludge. We need one global instantiation of this
* variable in each address space. So, libjack/client.c declares the
* actual storage. Other source files will see it as an extern. */
#define JACK_TIME_GLOBAL_DECL jack_time_t __jack_cpu_mhz
extern JACK_TIME_GLOBAL_DECL;

static inline jack_time_t
jack_get_microseconds (void) {
return get_cycles() / __jack_cpu_mhz;
}
extern jack_time_t (*_jack_get_microseconds)(void);

/*
* This is another kludge. It looks CPU-dependent, but actually it
* reflects the lack of standards for the Linux kernel formatting of
* /proc/cpuinfo.
*/
static inline jack_time_t
jack_get_mhz (void)
{
FILE *f = fopen("/proc/cpuinfo", "r");
if (f == 0)
{
perror("can't open /proc/cpuinfo\n");
exit(1);
}

for ( ; ; )
{
jack_time_t mhz;
int ret;
char buf[1000];

if (fgets(buf, sizeof(buf), f) == NULL) {
jack_error ("FATAL: cannot locate cpu MHz in "
"/proc/cpuinfo\n");
exit(1);
}

#if defined(__powerpc__)
ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz);
#elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \
defined(__x86_64__)
ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz);
#elif defined( __sparc__ )
ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz);
#elif defined( __mc68000__ )
ret = sscanf(buf, "Clocking: %" SCNu64, &mhz);
#elif defined( __s390__ )
ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz);
#else /* MIPS, ARM, alpha */
ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz);
#endif

if (ret == 1)
{
fclose(f);
return (jack_time_t)mhz;
}
}
}

/* This should only be called ONCE per process. */
static inline void
jack_init_time ()
jack_get_microseconds (void)
{
__jack_cpu_mhz = jack_get_mhz ();
return _jack_get_microseconds ();
}

#endif /* __jack_time_h__ */

+ 0
- 161
config/os/macosx/fakepoll.h View File

@@ -1,161 +0,0 @@

// fakepoll.h
// poll using select
// Warning: a call to this poll() takes about 4K of stack space.

// Greg Parker gparker-web@sealiesoftware.com December 2000
// This code is in the public domain and may be copied or modified without
// permission.

// Updated May 2002:
// * fix crash when an fd is less than 0
// * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
// * don't set POLLIN or POLLOUT in revents if it wasn't requested
// in events (only happens when an fd is in the poll set twice)

#ifndef _FAKE_POLL_H
#define _FAKE_POLL_H

#include <limits.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

typedef struct pollfd {
int fd; /* file desc to poll */
short events; /* events of interest on fd */
short revents; /* events that occurred on fd */
} pollfd_t;


// poll flags
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008

// synonyms
#define POLLNORM POLLIN
#define POLLPRI POLLIN
#define POLLRDNORM POLLIN
#define POLLRDBAND POLLIN
#define POLLWRNORM POLLOUT
#define POLLWRBAND POLLOUT

// ignored
#define POLLHUP 0x0010
#define POLLNVAL 0x0020

inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
{
struct timeval tv;
struct timeval *tvp;
fd_set readFDs, writeFDs, exceptFDs;
fd_set *readp, *writep, *exceptp;
struct pollfd *pollEnd, *p;
int selected;
int result;
int maxFD;

if (!pollSet) {
pollEnd = NULL;
readp = NULL;
writep = NULL;
exceptp = NULL;
maxFD = 0;
}
else {
pollEnd = pollSet + pollCount;
readp = &readFDs;
writep = &writeFDs;
exceptp = &exceptFDs;

FD_ZERO(readp);
FD_ZERO(writep);
FD_ZERO(exceptp);
// Find the biggest fd in the poll set
maxFD = 0;
for (p = pollSet; p < pollEnd; p++) {
if (p->fd > maxFD) maxFD = p->fd;
}

if (maxFD >= FD_SETSIZE) {
// At least one fd is too big
errno = EINVAL;
return -1;
}
// Transcribe flags from the poll set to the fd sets
for (p = pollSet; p < pollEnd; p++) {
if (p->fd < 0) {
// Negative fd checks nothing and always reports zero
} else {
if (p->events & POLLIN) FD_SET(p->fd, readp);
if (p->events & POLLOUT) FD_SET(p->fd, writep);
if (p->events != 0) {
FD_SET(p->fd, exceptp);
}
// POLLERR is never set coming in; poll() always reports errors
// But don't report if we're not listening to anything at all.
}
}
}
// poll timeout is in milliseconds. Convert to struct timeval.
// poll timeout == -1 : wait forever : select timeout of NULL
// poll timeout == 0 : return immediately : select timeout of zero
if (pollTimeout >= 0) {
tv.tv_sec = pollTimeout / 1000;
tv.tv_usec = (pollTimeout % 1000) * 1000;
tvp = &tv;
} else {
tvp = NULL;
}
selected = select(maxFD+1, readp, writep, exceptp, tvp);
if (selected < 0) {
// Error during select
result = -1;
}
else if (selected > 0) {
// Select found something
// Transcribe result from fd sets to poll set.
// Also count the number of selected fds. poll returns the
// number of ready fds; select returns the number of bits set.
int polled = 0;
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
if (p->fd < 0) {
// Negative fd always reports zero
} else {
if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
p->revents |= POLLIN;
}
if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
p->revents |= POLLOUT;
}
if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
p->revents |= POLLERR;
}

if (p->revents) polled++;
}
}
result = polled;
}
else {
// selected == 0, select timed out before anything happened
// Clear all result bits and return zero.
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
}
result = 0;
}

return result;
}

#endif

+ 156
- 23
config/os/macosx/poll.h View File

@@ -1,29 +1,162 @@
/*
Copyright (C) 2004 Jack O'Quin

Mac OS/X replacement for <sys/poll.h>. Overrides system version,
using <sysdeps/fakepoll.h> to emulate the needed features.
// fakepoll.h
// poll using select
// Warning: a call to this poll() takes about 4K of stack space.

// Greg Parker gparker-web@sealiesoftware.com December 2000
// This code is in the public domain and may be copied or modified without
// permission.

// Updated May 2002:
// * fix crash when an fd is less than 0
// * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
// * don't set POLLIN or POLLOUT in revents if it wasn't requested
// in events (only happens when an fd is in the poll set twice)

#ifndef _FAKE_POLL_H
#define _FAKE_POLL_H

#include <limits.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

typedef struct pollfd {
int fd; /* file desc to poll */
short events; /* events of interest on fd */
short revents; /* events that occurred on fd */
} pollfd_t;

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

$Id$
*/
// poll flags
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008

// synonyms
#define POLLNORM POLLIN
#define POLLPRI POLLIN
#define POLLRDNORM POLLIN
#define POLLRDBAND POLLIN
#define POLLWRNORM POLLOUT
#define POLLWRBAND POLLOUT

// ignored
#define POLLHUP 0x0010
#define POLLNVAL 0x0020

static inline int
poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
{
struct timeval tv;
struct timeval *tvp;
fd_set readFDs, writeFDs, exceptFDs;
fd_set *readp, *writep, *exceptp;
struct pollfd *pollEnd, *p;
int selected;
int result;
int maxFD;

if (!pollSet) {
pollEnd = NULL;
readp = NULL;
writep = NULL;
exceptp = NULL;
maxFD = 0;
}
else {
pollEnd = pollSet + pollCount;
readp = &readFDs;
writep = &writeFDs;
exceptp = &exceptFDs;

FD_ZERO(readp);
FD_ZERO(writep);
FD_ZERO(exceptp);
// Find the biggest fd in the poll set
maxFD = 0;
for (p = pollSet; p < pollEnd; p++) {
if (p->fd > maxFD) maxFD = p->fd;
}

if (maxFD >= FD_SETSIZE) {
// At least one fd is too big
errno = EINVAL;
return -1;
}
// Transcribe flags from the poll set to the fd sets
for (p = pollSet; p < pollEnd; p++) {
if (p->fd < 0) {
// Negative fd checks nothing and always reports zero
} else {
if (p->events & POLLIN) FD_SET(p->fd, readp);
if (p->events & POLLOUT) FD_SET(p->fd, writep);
if (p->events != 0) {
FD_SET(p->fd, exceptp);
}
// POLLERR is never set coming in; poll() always reports errors
// But don't report if we're not listening to anything at all.
}
}
}
// poll timeout is in milliseconds. Convert to struct timeval.
// poll timeout == -1 : wait forever : select timeout of NULL
// poll timeout == 0 : return immediately : select timeout of zero
if (pollTimeout >= 0) {
tv.tv_sec = pollTimeout / 1000;
tv.tv_usec = (pollTimeout % 1000) * 1000;
tvp = &tv;
} else {
tvp = NULL;
}
selected = select(maxFD+1, readp, writep, exceptp, tvp);
if (selected < 0) {
// Error during select
result = -1;
}
else if (selected > 0) {
// Select found something
// Transcribe result from fd sets to poll set.
// Also count the number of selected fds. poll returns the
// number of ready fds; select returns the number of bits set.
int polled = 0;
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
if (p->fd < 0) {
// Negative fd always reports zero
} else {
if ((p->events & POLLIN) && FD_ISSET(p->fd, readp)) {
p->revents |= POLLIN;
}
if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
p->revents |= POLLOUT;
}
if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
p->revents |= POLLERR;
}

#ifndef __poll_h__
#define __poll_h__
if (p->revents) polled++;
}
}
result = polled;
}
else {
// selected == 0, select timed out before anything happened
// Clear all result bits and return zero.
for (p = pollSet; p < pollEnd; p++) {
p->revents = 0;
}
result = 0;
}

#include <poll.h>
return result;
}

#endif /* __poll_h__ */
#endif

+ 0
- 28
config/os/macosx/portaudio.h View File

@@ -1,28 +0,0 @@
/*
Copyright (C) 2004 Jack O'Quin

Mac OS/X specific defines.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

$Id$
*/

#ifndef _macosx_portaudio
#define _macosx_portaudio 1

#include <PortAudio.h>

#endif /* _macosx_portaudio */

+ 2
- 19
config/os/macosx/time.h View File

@@ -21,32 +21,15 @@
#ifndef __jack_time_h__
#define __jack_time_h__

/*
* This is the MacOSX version of <jack/time.h>. It overrides the
* generic version via the configure.hosts mechanism.
*/
#include <jack/types.h>
#include <mach/mach_time.h>

/* This is a kludge. We need one global instantiation of this
* variable in each address space. So, libjack/client.c declares the
* actual storage. Other source files will see it as an extern. */
#define JACK_TIME_GLOBAL_DECL double __jack_time_ratio
extern JACK_TIME_GLOBAL_DECL;
extern double __jack_time_ratio;

static inline jack_time_t
jack_get_microseconds(void)
{
return mach_absolute_time () * __jack_time_ratio;
}

/* This should only be called ONCE per process. */
static inline void
jack_init_time ()
{
mach_timebase_info_data_t info;
mach_timebase_info(&info);
__jack_time_ratio = ((float)info.numer/info.denom) / 1000;
return (jack_time_t) mach_absolute_time () * __jack_time_ratio;
}

#endif /* __jack_time_h__ */

+ 0
- 23
config/sysdeps/Makefile.am View File

@@ -1,23 +0,0 @@
# This directory contains links to platform-dependent headers in the
# source tree. None are installed or distributed from here. Remember
# that the build tree and the source tree are not always the same.

MAINTAINERCLEANFILES = Makefile.in
CLEANFILES = *.h

# Link all relevant headers into the `sysdeps' directory. The order
# of these loops determines header file precedence.

all-local:
for h in ${top_srcdir}/config/cpu/generic/*.h; do \
$(LN_S) -f $$h .; \
done
for h in ${top_srcdir}/config/@cpu_include_dir@/*.h; do \
$(LN_S) -f $$h .; \
done
for h in ${top_srcdir}/config/os/generic/*.h; do \
$(LN_S) -f $$h .; \
done
for h in ${top_srcdir}/config/@os_include_dir@/*.h; do \
$(LN_S) -f $$h .; \
done

+ 24
- 0
config/sysdeps/atomicity.h View File

@@ -0,0 +1,24 @@
#ifndef _jack_sysdep_atomicity_h_
#define _jack_sysdep_atomicity_h_

#if defined(__i386__)

#include <config/cpu/i386/atomicity.h>

#elif defined(__x86_64)

/* x86_64 can use rdtsc just like i[456]86 */

#include <config/cpu/i386/atomicity.h>

#elif defined(__powerpc__) || defined(__ppc__) /* linux and OSX use different tokens */

#include <config/cpu/powerpc/atomicity.h>

#else

#include <config/cpu/generic/atomicity.h>

#endif /* processor selection */

#endif /* _jack_sysdep_atomicity_h_ */

+ 28
- 0
config/sysdeps/cycles.h View File

@@ -0,0 +1,28 @@
#ifndef _jack_sysdep_cycles_h_
#define _jack_sysdep_cycles_h_

#if defined(__i386__)
/* technically, i386 doesn't have a cycle counter, but
running JACK on a real i386 seems like a ridiculuous
target and gcc defines this for the entire x86 family
including the [456]86 that do have the counter.
*/

#include <config/cpu/i386/cycles.h>

#elif defined(__x86_64)

#include <config/cpu/i486/cycles.h>

#elif defined(__powerpc__) || defined(__ppc__) /* linux and OSX gcc use different tokens */

#include <config/cpu/powerpc/cycles.h>

#else

#include <config/cpu/generic/cycles.h>

#endif /* processor selection */

#endif /* _jack_sysdep_cycles_h_ */

+ 8
- 0
config/sysdeps/getopt.h View File

@@ -0,0 +1,8 @@
#ifndef _jack_sysdep_getopt_h_
#define _jack_sysdep_getopt_h_

#if defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/getopt.h>
#endif

#endif /* _jack_sysdep_getopt_h_ */

+ 10
- 0
config/sysdeps/ipc.h View File

@@ -0,0 +1,10 @@
#ifndef _jack_sysdep_ipc_h_
#define _jack_sysdep_ipc_h_

#if defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/ipc.h>
#else
#include <config/os/generic/ipc.h>
#endif

#endif /* _jack_sysdep_ipc_h_ */

+ 8
- 0
config/sysdeps/mach_port.h View File

@@ -0,0 +1,8 @@
#ifndef _jack_sysdep_mach_port_h_
#define _jack_sysdep_mach_port_h_

#if defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/mach_port.h>
#endif

#endif /* _jack_sysdep_mach_port_h_ */

+ 8
- 0
config/sysdeps/pThreadUtilities.h View File

@@ -0,0 +1,8 @@
#ifndef _jack_sysdep_pThreadUtilities_h_
#define _jack_sysdep_pThreadUtilities_h_

#if defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/pThreadUtilities.h>
#endif

#endif /* _jack_sysdep_pThreadUtilities_h_ */

+ 14
- 0
config/sysdeps/poll.h View File

@@ -0,0 +1,14 @@
#ifndef _jack_sysdep_poll_h_
#define _jack_sysdep_poll_h_

#if defined(__MACH__) && defined(__APPLE__)

#include <config/os/macosx/poll.h>

#else

#include <poll.h>

#endif

#endif /* _jack_sysdep_poll_h_ */

+ 8
- 0
config/sysdeps/portaudio.h View File

@@ -0,0 +1,8 @@
#ifndef _jack_sysdep_portaudio_h_
#define _jack_sysdep_portaudio_h_

#if defined(__MACH__) && defined(__APPLE__)
#include <PortAudio.h>
#endif

#endif /* _jack_sysdep_portaudio_h_ */

+ 12
- 0
config/sysdeps/time.c View File

@@ -0,0 +1,12 @@
#ifndef _jack_sysdep_time_c_
#define _jack_sysdep_time_c_

#if defined(__gnu_linux__)
#include <config/os/gnu-linux/time.c>
#elif defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/time.c>
#else
#include <config/os/generic/time.c>
#endif

#endif /* _jack_sysdep_time_c_ */

+ 12
- 0
config/sysdeps/time.h View File

@@ -0,0 +1,12 @@
#ifndef _jack_sysdep_time_h_
#define _jack_sysdep_time_h_

#if defined(__gnu_linux__)
#include <config/os/gnu-linux/time.h>
#elif defined(__MACH__) && defined(__APPLE__)
#include <config/os/macosx/time.h>
#else
#include <config/os/generic/time.h>
#endif

#endif /* _jack_sysdep_time_h_ */

+ 52
- 8
configure.ac View File

@@ -78,13 +78,46 @@ AM_PROG_LIBTOOL
AC_PROG_LN_S
AC_C_BIGENDIAN

# configure CPU and OS dependencies for host platform
AC_MSG_CHECKING([platform dependencies])
source $srcdir/config/configure.host
AC_MSG_RESULT([${os_include_dir}, ${cpu_include_dir}])

case "${host_os}" in
freebsd*)
# current FreeBSD header files conflict with the OSS driver's
# barrier code, this may be fixed in 5.3, stay tuned.
USE_BARRIER="no"
;;
darwin*)
JACK_THREAD_STACK_TOUCH=10000 # need small realtime stack
JACK_CPP_VARARGS_BROKEN=1
JACK_DO_NOT_MLOCK=1
JACK_USE_MACH_THREADS=1
OS_LDFLAGS="-framework CoreAudio -framework CoreServices -framework AudioUnit"
TRY_POSIX_SHM=yes # POSIX shm works better
;;
esac

AC_SUBST(OS_LDFLAGS)
AC_SUBST(os_include_dir)
AC_SUBST(cpu_include_dir)

#
# We need to establish suitable defaults for a 64-bit OS
libnn=lib
case "${host_os}" in
linux*)
case "${host_cpu}" in
x86_64|mips64|ppc64|sparc64|s390x)
libnn=lib64
;;
esac
;;
solaris*)
## libnn=lib/sparcv9 ## on 64-bit only, but that's compiler-specific
;;
esac

## take care not to override the command-line setting
if test "${libdir}" = '${exec_prefix}/lib'; then
libdir='${exec_prefix}/'${libnn}
fi

# system-dependent config.h values
test "x$JACK_THREAD_STACK_TOUCH" = "x" && JACK_THREAD_STACK_TOUCH=1000000
@@ -130,6 +163,16 @@ AC_CHECK_FUNCS(on_exit atexit)
AC_CHECK_FUNCS(posix_memalign)
AC_CHECK_LIB(m, sin)

AC_CHECK_FUNC(clock_gettime,
[
AC_DEFINE(HAVE_CLOCK_GETTIME,1,"Whether or not clock_gettime can be found in system libraries")
],
AC_CHECK_LIB(rt, clock_getttime,
[
AC_DEFINE(HAVE_CLOCK_GETTIME,1,"Whether or not clock_gettime can be found in system libraries")
])
)

# should we use mlockall() on this platform?
if test "x$JACK_DO_NOT_MLOCK" = "x"; then
AC_CHECK_HEADER(sys/mman.h,
@@ -448,9 +491,10 @@ AC_ARG_ENABLE(stripped-jackd,

# plugins go in the addon dir.

AS_AC_EXPAND(ADDON_DIR,${libdir}/jack)
ADDON_DIR='${libdir}/jack'
AC_SUBST(ADDON_DIR)
AC_DEFINE_UNQUOTED(ADDON_DIR,"$ADDON_DIR",[Directory for plugins])
AS_AC_EXPAND(ADDON_DIR_EXPANDED,${libdir}/jack)
AC_DEFINE_UNQUOTED(ADDON_DIR,"$ADDON_DIR_EXPANDED",[Directory for plugins])

AC_ARG_WITH(html-dir,
[ --with-html-dir=PATH where to install the html documentation])
@@ -622,7 +666,6 @@ AM_CONDITIONAL(STRIPPED_JACKD, $STRIPPED_JACKD)
AC_OUTPUT(
Makefile
config/Makefile
config/sysdeps/Makefile
doc/Makefile
doc/reference.doxygen
drivers/Makefile
@@ -656,6 +699,7 @@ echo \| Build with CoreAudio support.......................... : $HAVE_COREAUDIO
echo \| Build with PortAudio support.......................... : $HAVE_PA
echo \| Compiler optimization flags........................... : $JACK_OPT_CFLAGS
echo \| Compiler full flags................................... : $CFLAGS
echo \| Install dir for libjack + backends.................... : $libdir/jack
echo \|
echo \| Default driver backend................................ : $JACK_DEFAULT_DRIVER
echo \| Shared memory interface............................... : $JACK_SHM_TYPE


+ 2
- 2
example-clients/Makefile.am View File

@@ -114,11 +114,11 @@ jack_unload_LDFLAGS = @OS_LDFLAGS@
jack_unload_LDADD = ../libjack/libjack.la

jack_midiseq_SOURCES = midiseq.c
jack_midiseq_LDFLAGS = -lrt -ldl -lpthread
jack_midiseq_LDFLAGS = @OS_LDFLAGS@
jack_midiseq_LDADD = ../libjack/libjack.la

jack_midisine_SOURCES = midisine.c
jack_midisine_LDFLAGS = -lrt -ldl -lpthread -lm
jack_midisine_LDFLAGS = @OS_LDFLAGS@
jack_midisine_LDADD = ../libjack/libjack.la

#


+ 2
- 1
example-clients/metro.c View File

@@ -123,6 +123,7 @@ main (int argc, char *argv[])
char *client_name = 0;
char *bpm_string = "bpm";
int verbose = 0;
jack_status_t status;

const char *options = "f:A:D:a:d:b:n:thv";
struct option long_options[] =
@@ -208,7 +209,7 @@ main (int argc, char *argv[])
client_name = (char *) malloc (9 * sizeof (char));
strcpy (client_name, "metro");
}
if ((client = jack_client_new (client_name)) == 0) {
if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) {
fprintf (stderr, "jack server not running?\n");
return 1;
}


+ 2
- 0
jack/engine.h View File

@@ -169,6 +169,8 @@ int internal_client_request (void* ptr, jack_request_t *request);
int jack_get_fifo_fd (jack_engine_t *engine,
unsigned int which_fifo);

extern jack_timer_type_t clock_source;

extern jack_client_internal_t *
jack_client_internal_by_id (jack_engine_t *engine, jack_client_id_t id);



+ 12
- 0
jack/internal.h View File

@@ -42,6 +42,17 @@ extern void jack_error (const char *fmt, ...);
#include <jack/types.h>
#include <jack/port.h>
#include <jack/transport.h>

typedef enum {
JACK_TIMER_SYSTEM_CLOCK,
JACK_TIMER_CYCLE_COUNTER,
JACK_TIMER_HPET,
} jack_timer_type_t;

void jack_init_time ();
void jack_set_clock_source (jack_timer_type_t);
const char* jack_clock_source_name (jack_timer_type_t);

#include <sysdeps/time.h>
#include <sysdeps/atomicity.h>

@@ -130,6 +141,7 @@ typedef struct {
jack_time_t sync_time_left;
jack_frame_timer_t frame_timer;
int32_t internal;
jack_timer_type_t clock_source;
pid_t engine_pid;
jack_nframes_t buffer_size;
int8_t real_time;


+ 4
- 0
jack/thread.h View File

@@ -27,6 +27,10 @@ extern "C" {

#include <pthread.h>

/* use 512KB stack per thread - the default is way too high to be feasible
* with mlockall() on many systems */
#define THREAD_STACK 524288
/** @file thread.h
*
* Library functions to standardize thread creation for JACK and its


+ 31
- 11
jackd/engine.c View File

@@ -78,6 +78,8 @@ typedef struct _jack_driver_info {
dlhandle handle;
} jack_driver_info_t;

jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;

static int jack_port_assign_buffer (jack_engine_t *,
jack_port_internal_t *);
static jack_port_internal_t *jack_get_port_by_name (jack_engine_t *,
@@ -1540,6 +1542,30 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
uid_t euid = geteuid ();
#endif /* USE_CAPABILITIES */

/* before we start allocating resources, make sure that if realtime was requested that we can
actually do it.
*/

if (realtime) {
if (jack_acquire_real_time_scheduling (pthread_self(), 10) != 0) {
/* can't run realtime - time to bomb */
return NULL;
}

jack_drop_real_time_scheduling (pthread_self());

#ifdef USE_MLOCK

if (do_mlock && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) {
jack_error ("cannot lock down memory for jackd (%s)",
strerror (errno));
#ifdef ENSURE_MLOCK
return NULL;
#endif /* ENSURE_MLOCK */
}
#endif /* USE_MLOCK */
}

/* start a thread to display messages from realtime threads */
jack_messagebuffer_init();

@@ -1675,6 +1701,11 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
engine->control->xrun_delayed_usecs = 0;
engine->control->max_delayed_usecs = 0;

jack_set_clock_source (clock_source);
engine->control->clock_source = clock_source;

VERBOSE (engine, "clock source = %s\n", jack_clock_source_name (clock_source));

engine->control->frame_timer.frames = frame_time_offset;
engine->control->frame_timer.reset_pending = 0;
engine->control->frame_timer.current_wakeup = 0;
@@ -1726,17 +1757,6 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
}
#endif /* USE_CAPABILITIES */

#ifdef USE_MLOCK

if (realtime && do_mlock && (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) {
jack_error ("cannot lock down memory for jackd (%s)",
strerror (errno));
#ifdef ENSURE_MLOCK
return NULL;
#endif /* ENSURE_MLOCK */
}
#endif /* USE_MLOCK */

engine->control->engine_ok = 1;

snprintf (engine->fifo_prefix, sizeof (engine->fifo_prefix),


+ 3
- 0
jackd/jackd.1.in View File

@@ -96,6 +96,9 @@ Unlock libraries GTK+, QT, FLTK, Wine.
\fB\-v, \-\-verbose\fR
Give verbose output.
.TP
\fB\-c, \-\-clocksource\fR (\fI c(ycle)\fR | \fI h(pet) \fR | \fI s(ystem) \fR)
Select a specific wall clock (Cycle Counter, HPET timer, System timer).
.TP
\fB\-V, \-\-version\fR
Print the current JACK version number and exit.
.SS ALSA BACKEND OPTIONS


+ 17
- 1
jackd/jackd.c View File

@@ -22,6 +22,7 @@
#include <config.h>

#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <getopt.h>
#include <sys/types.h>
@@ -368,6 +369,7 @@ static void usage (FILE *file)
" [ --port-max OR -p maximum-number-of-ports]\n"
" [ --debug-timer OR -D ]\n"
" [ --verbose OR -v ]\n"
" [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
" [ --silent OR -s ]\n"
" [ --version OR -V ]\n"
" -d backend [ ... backend args ... ]\n"
@@ -505,7 +507,7 @@ main (int argc, char *argv[])

{
jack_driver_desc_t * desc;
const char *options = "-ad:P:uvshVRTFl:t:mn:p:";
const char *options = "-ad:P:uvshVRTFl:t:mn:p:c:";
struct option long_options[] =
{
{ "driver", 1, 0, 'd' },
@@ -521,6 +523,7 @@ main (int argc, char *argv[])
{ "temporary", 0, 0, 'T' },
{ "version", 0, 0, 'V' },
{ "silent", 0, 0, 's' },
{ "clock-source", 1, 0, 'c' },
{ 0, 0, 0, 0 }
};
int opt = 0;
@@ -544,6 +547,19 @@ main (int argc, char *argv[])
long_options, &option_index)) != EOF) {
switch (opt) {

case 'c':
if (tolower (optarg[0]) == 'h') {
clock_source = JACK_TIMER_HPET;
} else if (tolower (optarg[0]) == 'c') {
clock_source = JACK_TIMER_CYCLE_COUNTER;
} else if (tolower (optarg[0]) == 's') {
clock_source = JACK_TIMER_SYSTEM_CLOCK;
} else {
usage (stderr);
return -1;
}
break;

case 'd':
seen_driver = 1;
driver_name = optarg;


+ 2
- 1
libjack/Makefile.am View File

@@ -16,10 +16,11 @@ SOURCE_FILES = \
messagebuffer.c \
pool.c \
port.c \
midiport.c \
midiport.c \
ringbuffer.c \
shm.c \
thread.c \
time.c \
timestamps.c \
transclient.c \
unlock.c


+ 4
- 2
libjack/client.c View File

@@ -50,12 +50,12 @@
#include <jack/intsimd.h>

#include <sysdeps/time.h>
JACK_TIME_GLOBAL_DECL; /* One instance per process. */

#include "local.h"

#include <sysdeps/poll.h>
#include <sysdeps/ipc.h>
#include <sysdeps/cycles.h>

#ifdef JACK_USE_MACH_THREADS
#include <sysdeps/pThreadUtilities.h>
@@ -77,7 +77,6 @@ int cpu_type = 0;
#define event_fd pollfd[EVENT_POLL_INDEX].fd
#define graph_wait_fd pollfd[WAIT_POLL_INDEX].fd


typedef struct {
int status;
struct _jack_client *client;
@@ -992,6 +991,9 @@ jack_client_open (const char *client_name,
client->engine = (jack_control_t *) jack_shm_addr (&client->engine_shm);

/* initialize clock source as early as possible */
jack_set_clock_source (client->engine->clock_source);

/* now attach the client control block */
client->control_shm = res.client_shm;
if (jack_attach_shm (&client->control_shm)) {


+ 3
- 1
libjack/local.h View File

@@ -1,7 +1,7 @@
#ifndef __jack_libjack_local_h__
#define __jack_libjack_local_h__

/* Client data structure, in the client's address space. */
/* Client data structure, in the client address space. */
struct _jack_client {

jack_control_t *engine;
@@ -52,4 +52,6 @@ extern jack_port_t *jack_port_new (const jack_client_t *client,

extern void *jack_zero_filled_buffer;

extern void jack_set_clock_source (jack_timer_type_t);

#endif /* __jack_libjack_local_h__ */

+ 6
- 0
libjack/thread.c View File

@@ -159,6 +159,12 @@ jack_client_create_thread (jack_client_t* client,
return result;
}

result = pthread_attr_setstacksize(&attr, THREAD_STACK);
if (result) {
log_result("setting thread stack size", result);
return result;
}

thread_args = (jack_thread_arg_t *) malloc (sizeof (jack_thread_arg_t));

thread_args->client = client;


Loading…
Cancel
Save