git-svn-id: svn+ssh://jackaudio.org/trunk/jack@948 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.109.0
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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__ */ | |||
| @@ -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 */ | |||
| @@ -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__ */ | |||
| @@ -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 */ | |||
| @@ -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> | |||
| @@ -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__ */ | |||
| @@ -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__ */ | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 */ | |||
| @@ -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__ */ | |||
| @@ -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 | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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_ */ | |||
| @@ -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 | |||
| @@ -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 | |||
| # | |||
| @@ -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; | |||
| } | |||
| @@ -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); | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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), | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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)) { | |||
| @@ -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__ */ | |||
| @@ -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; | |||