Re: [linux-audio-dev] Sequencer Sync Woes

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] Sequencer Sync Woes
From: Karl MacMillan (karlmac_AT_peabody.jhu.edu)
Date: Tue Feb 06 2001 - 07:29:16 EET


Another option is to use select on null file descriptors. The nanosleep
man page mentions that on intel the minimum sleep is 10ms or if the
process SCHED_FIFO and the pause is less that 2ms it will busy wait (which
is not what you want of course). Paul's suggestion will give you better
resolution at the cost of portability (which you may or may not care
about). The select trick should, I think, give you better than 10ms
though I don't have numbers to prove this.

Karl

On Mon, 5 Feb 2001, Paul Davis wrote:

> > So, maybe I'm ok to use /dev/midi00? Is that what everyone else uses?
> >Am I doing something wrong in my loop? Is there a way to yield a
> >smaller amount of time maybe so I can poll more often? My pseudocode:
> >
> > loop {
> > nanosleep( 5ms ); // something less than HZ I guess?
> > // let the editor get some cpu
> >
> > diff = gettimeofday - time_last_tick_we_sent_was_due
> >
> > if diff > time_per_tick:
> > - output a sync tick along with the notes for this tick
> > - remember the time that tick was supposed to be sent, we use
> > that for the difference above
> > fi
> > }
> >
> > Should I write a kernel module which I can use to queue writes?
>
> i'd use this (below). the key is to hook into the call to RTC::tick().
>
> the object below starts its own thread which sets up the RTC to
> provide a periodic wakeup (freq up to 8kHz). that thread runs the
> RTC::do_work() function, which basically just poll(2)'s the RTC fd,
> and sends the "tick()" signal every time it wakes up. for the non
> libsigc++, think of a signal as a linked list of callbacks that get
> executed en-masse.
>
> the design assumes that the thread will run with SCHED_FIFO priority
> and has its memory locked down. the responsibility for checking the
> *actual* time lies with whatever decides to receive the "tick()"
> signal.
>
> this is very similar to the way SoftWerk works too, except that it
> uses SIGIO-based notification from the RTC, not poll(2)-based wakeup.
>
> --p
>
> /*
> Copyright (C) 2001 Paul Davis
>
> 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.
>
> 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: rtc.cc,v 1.1 2001/01/16 17:19:47 pbd Exp $
> */
>
> #include <stdio.h>
> #include <linux/rtc.h>
> #include <string.h>
> #include <errno.h>
> #include <unistd.h>
> #include <poll.h>
> #include <fcntl.h>
> #include <math.h>
> #include <sys/ioctl.h>
>
> #include "ardour.h"
> #include "rtc.h"
>
> using namespace ARDOUR;
>
> RealTimeClock::RealTimeClock ()
> : QMThread ("realtime clock", start_thread, this, true, 8)
> {
> if ((rtc_fd = open ("/dev/rtc", O_RDONLY)) < 0) {
> error << "RealTimeClock: cannot open /dev/rtc ("
> << strerror (errno)
> << ')'
> << endmsg;
> throw failed_constructor();
> }
>
> if (fcntl (rtc_fd, F_SETOWN, getpid()) < 0) {
> error << "RealTimeClock: cannot set ownership of /dev/rtc ("
> << strerror (errno)
> << ')'
> << endmsg;
> throw failed_constructor();
> }
>
> rtc_running = false;
> current_hz = 0;
> }
>
> RealTimeClock::~RealTimeClock ()
>
> {
> stop_periodic_interrupts ();
> close (rtc_fd);
> }
>
> void *
> RealTimeClock::start_thread (void *arg)
>
> {
> RealTimeClock *rtc = (RealTimeClock *) arg;
> return rtc->main ();
> }
>
> void *
> RealTimeClock::do_work ()
>
> {
> unsigned long rtc_data;
>
> start_periodic_interrupts ();
>
> while (!work_no_more()) {
> struct pollfd pfd;
> pfd.fd = rtc_fd;
> pfd.events = POLLIN | POLLERR;
>
> again:
> if (poll (&pfd, 1, 100000) < 0) {
> if (errno == EINTR) {
> // this happens mostly when run
> // under gdb, or when exiting due to a signal
> goto again;
> }
>
> error << "RealTimeClock: poll call failed ("
> << strerror (errno)
> << ')'
> << endmsg;
>
> return (void *) -1;
> }
> read (rtc_fd, &rtc_data, sizeof (rtc_data));
> tick ();
> }
>
> return 0;
> }
>
> bool
> RealTimeClock::set_interval (guint32 usecs)
>
> {
> int req_hz = (int) floor ((1000000.0/usecs));
> int hz = 2;
> bool restart;
>
> hz = 2;
> while (hz < req_hz) {
> hz *= 2;
> }
>
> if (hz == current_hz) {
> return true;
> }
>
> restart = stop_periodic_interrupts ();
>
> if (ioctl(rtc_fd, RTC_IRQP_SET, hz) < 0) {
> error << "RealTimeClock: cannot set periodic interval ("
> << strerror (errno)
> << ')'
> << endmsg;
> return -1;
> }
>
> current_hz = hz;
>
> if (restart) {
> start_periodic_interrupts ();
> }
>
> return true;
> }
>
> bool
> RealTimeClock::start_periodic_interrupts ()
>
> {
> if (!rtc_running) {
> if (ioctl (rtc_fd, RTC_PIE_ON, 0) < 0) {
> error << "RealTimeClock: cannot start periodic interrupts ("
> << strerror (errno)
> << ')'
> << endmsg;
> return false;
> }
> rtc_running = true;
> }
> return rtc_running;
> }
>
> bool
> RealTimeClock::stop_periodic_interrupts ()
>
> {
> bool was_running = rtc_running;
>
> if (rtc_running) {
> if (ioctl (rtc_fd, RTC_PIE_OFF, 0) < 0) {
> error << "RealTimeClock: cannot stop periodic interrupts ("
> << strerror (errno)
> << ')'
> << endmsg;
> return rtc_running;
> }
> rtc_running = false;
> }
>
> return was_running;
> }
>
> /*
> Copyright (C) 2001 Paul Davis
>
> 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.
>
> 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: rtc.h,v 1.1 2001/01/16 17:19:47 pbd Exp $
> */
>
> #ifndef __ardour_rtc_h__
> #define __ardour_rtc_h__
>
>
> #include <pbd/thread.h>
> #include <sigc++/signal_system.h>
>
> class RealTimeClock : public QMThread, public SigC::Object
>
> {
> public:
> RealTimeClock ();
> virtual ~RealTimeClock();
>
> bool set_interval (unsigned int usecs);
>
> SigC::Signal0<void> tick;
>
> private:
> int rtc_fd;
> int current_hz;
> bool rtc_running;
> bool start_periodic_interrupts ();
> bool stop_periodic_interrupts ();
>
> static void *start_thread (void *);
> void *do_work ();
> };
>
> #endif /* __ardour_rtc_h__ */
>

_____________________________________________________
| Karl W. MacMillan |
| Computer Music Department |
| Peabody Institute of the Johns Hopkins University |
| karlmac_AT_peabody.jhu.edu |
| www.peabody.jhu.edu/~karlmac |
-----------------------------------------------------


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Tue Feb 06 2001 - 07:43:58 EET