Commit ae9a0281 authored by sletz's avatar sletz
Browse files

Tagging the 0.58 release of the 'jackmp' project.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/tags/release-0.58@1229 0c269be4-1314-0410-8aa9-9f06e86f4224
parents 6dd5decc 46ab6341
---------------------------
Jackdmp changes log
---------------------------
---------------------------
2006-09-06 Stephane Letz <letz@grame.fr>
* Correct coreaudio driver (input was not working since 0.55 version).
2006-09-04 Stephane Letz <letz@grame.fr>
......
---------------------------
Jackdmp changes log
---------------------------
2006-09-06 Stephane Letz <letz@grame.fr>
* Correct coreaudio driver (input was not working since 0.55 version).
2006-09-04 Stephane Letz <letz@grame.fr>
* Correct Windows VC++ projects.
2006-09-03 Stephane Letz <letz@grame.fr>
* First import of version 0.58 code
This diff is collapsed.
/*
Copyright (C) 2004-2006 Grame
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.
*/
#include "JackAtomic.h"
#include "JackActivationCount.h"
#include "JackConstants.h"
#include "JackClientControl.h"
#include "JackError.h"
namespace Jack
{
bool JackActivationCount::Signal(JackSynchro* synchro, JackClientControl* control)
{
if (fValue == 0) {
// Transfer activation to next clients
jack_error("JackActivationCount::Signal value = 0 ref = %ld", control->fRefNum);
return synchro->Signal();
} else if (DEC_ATOMIC(&fValue) == 1) {
return synchro->Signal();
} else {
return true;
}
}
} // end of namespace
/*
Copyright (C) 2004-2006 Grame
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.
*/
#ifndef __JackActivationCount__
#define __JackActivationCount__
#include "JackSynchro.h"
#include "JackTime.h"
namespace Jack
{
struct JackClientControl;
/*!
\brief Client activation counter.
*/
class JackActivationCount
{
private:
long fValue;
long fCount;
public:
JackActivationCount(): fValue(0), fCount(0)
{}
virtual ~JackActivationCount()
{}
bool Signal(JackSynchro* synchro, JackClientControl* control);
inline void Reset()
{
fValue = fCount;
}
inline void SetValue(int val)
{
fCount = val;
}
inline void IncValue()
{
fCount++;
}
inline void DecValue()
{
fCount--;
}
inline int GetValue() const
{
return fValue;
}
};
} // end of namespace
#endif
/*
Copyright (C) 2004-2006 Grame
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.
*/
#ifndef __JackAtomic__
#define __JackAtomic__
typedef unsigned short UInt16;
typedef unsigned long UInt32;
typedef long SInt32;
#ifdef WIN32
#include <windows.h>
typedef ULONGLONG UInt64;
#else
typedef unsigned long long UInt64;
#endif
#if defined(__APPLE__)
#if defined(__ppc__)
static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
{
register int result;
asm volatile (
"# CAS \n"
" lwarx r0, 0, %1 \n" // creates a reservation on addr
" cmpw r0, %2 \n" // test value at addr
" bne- 1f \n"
" sync \n" // synchronize instructions
" stwcx. %3, 0, %1 \n" // if the reservation is not altered
// stores the new value at addr
" bne- 1f \n"
" li %0, 1 \n"
" b 2f \n"
"1: \n"
" li %0, 0 \n"
"2: \n"
: "=r" (result)
: "r" (addr), "r" (value), "r" (newvalue)
: "r0"
);
return result;
}
#endif
#if defined(__i386__) || defined(__x86_64__)
#ifdef __SMP__
# define LOCK "lock ; "
#else
# define LOCK ""
#endif
static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
{
register char ret;
__asm__ __volatile__ (
"# CAS \n\t"
LOCK "cmpxchg %2, (%1) \n\t"
"sete %0 \n\t"
: "=a" (ret)
: "c" (addr), "d" (newvalue), "a" (value)
);
return ret;
}
#endif
#endif
#ifdef __linux__
#ifdef __PPC__
static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
{
register int result;
register UInt32 tmp;
asm volatile (
"# CAS \n"
" lwarx %4, 0, %1 \n" // creates a reservation on addr
" cmpw %4, %2 \n" // test value at addr
" bne- 1f \n"
" sync \n" // synchronize instructions
" stwcx. %3, 0, %1 \n" // if the reservation is not altered
// stores the new value at addr
" bne- 1f \n"
" li %0, 1 \n"
" b 2f \n"
"1: \n"
" li %0, 0 \n"
"2: \n"
: "=r" (result)
: "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
);
return result;
}
#endif
#if defined(__i386__) || defined(__x86_64__)
#ifdef __SMP__
# define LOCK "lock ; "
#else
# define LOCK ""
#endif
static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
{
register char ret;
__asm__ __volatile__ (
"# CAS \n\t"
LOCK "cmpxchg %2, (%1) \n\t"
"sete %0 \n\t"
: "=a" (ret)
: "c" (addr), "d" (newvalue), "a" (value)
);
return ret;
}
#endif
#endif
#ifdef WIN32
#ifdef __SMP__
# define LOCK lock
#else
# define LOCK
#endif
#define inline __inline
//----------------------------------------------------------------
// CAS functions
//----------------------------------------------------------------
inline char CAS (volatile UInt32 value, UInt32 newvalue, volatile void * addr)
{
register char c;
__asm {
push ebx
push esi
mov esi, addr
mov eax, value
mov ebx, newvalue
LOCK cmpxchg dword ptr [esi], ebx
sete c
pop esi
pop ebx
}
return c;
}
#endif
static inline long INC_ATOMIC(volatile SInt32* val)
{
SInt32 actual;
do {
actual = *val;
} while (!CAS(actual, actual + 1, val));
return actual;
}
static inline long DEC_ATOMIC(volatile SInt32* val)
{
SInt32 actual;
do {
actual = *val;
} while (!CAS(actual, actual - 1, val));
return actual;
}
#endif
/*
Copyright (C) 2004-2006 Grame
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.
*/
#ifndef __JackAtomicArrayState__
#define __JackAtomicArrayState__
#include "JackAtomic.h"
#include "JackError.h"
#include <string.h> // for memcpy
namespace Jack
{
/*!
\brief Counter for CAS
*/
struct AtomicArrayCounter
{
union {
struct {
unsigned char fByteVal[4];
}
scounter;
UInt32 fLongVal;
}info;
AtomicArrayCounter& operator=(volatile AtomicArrayCounter& obj)
{
info.fLongVal = obj.info.fLongVal;
return *this;
}
};
#define Counter1(e) (e).info.fLongVal
#define GetIndex1(e, state) ((e).info.scounter.fByteVal[state])
#define SetIndex1(e, state, val) ((e).info.scounter.fByteVal[state] = val)
#define IncIndex1(e, state) ((e).info.scounter.fByteVal[state]++)
#define SwapIndex1(e, state) (((e).info.scounter.fByteVal[0] == state) ? 0 : state)
/*!
\brief A class to handle serveral states in a lock-free manner
Requirement:
- a "current" state
- several possible "pending" state
- an TrySwitchState(int state) operation to atomically switch a "pending" to the "current" state (the pending becomes the current).
The TrySwitchState operation returns a "current" state (either the same if switch fails or the new one; one can know if the switch has succeeded)
- a WriteStartState(int state) returns a "pending" state to be written into
- a WriteStartStop(int state) make the written "pending" state become "switchable"
Different pending states can be written independantly and concurently.
GetCurrentIndex() *must* return an increasing value to be able to check reading current state coherency
The fCounter is an array of indexes to access te current and 3 different "pending" states.
¥ WriteNextStateStart(int index) must return a valid state to be written into, and must invalidate state "index" ==> cur state switch.
¥ WriteNextStateStop(int index) makes the "index" state become "switchable" with the current state.
¥ TrySwitchState(int index) must detect that pending state is a new state, and does the switch
¥ ReadCurrentState() must return the state
¥ GetCurrentIndex() must return an index increased each new switch.
¥ WriteNextStateStart(int index1) and WriteNextStateStart(int index2) can be interleaved
[switch counter][index state][index state][cur index]
*/
// CHECK livelock
template <class T>
class JackAtomicArrayState
{
protected:
// fState[0] ==> current
// fState[1] ==> pending
// fState[2] ==> request
T fState[3];
volatile AtomicArrayCounter fCounter;
UInt32 WriteNextStateStartAux(int state, bool* result)
{
AtomicArrayCounter old_val;
AtomicArrayCounter new_val;
UInt32 cur_index;
UInt32 next_index;
bool need_copy;
do {
old_val = fCounter;
new_val = old_val;
*result = GetIndex1(new_val, state);
cur_index = GetIndex1(new_val, 0);
next_index = SwapIndex1(fCounter, state);
need_copy = (GetIndex1(new_val, state) == 0); // Written = false, switch just occured
SetIndex1(new_val, state, 0); // Written = false, invalidate state
} while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
if (need_copy)
memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
return next_index;
}
void WriteNextStateStopAux(int state)
{
AtomicArrayCounter old_val;
AtomicArrayCounter new_val;
do {
old_val = fCounter;
new_val = old_val;
SetIndex1(new_val, state, 1); // Written = true, state becomes "switchable"
} while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
}
public:
JackAtomicArrayState()
{
JackLog("JackAtomicArrayState constructor\n");
Counter1(fCounter) = 0;
}
~JackAtomicArrayState() // Not virtual ??
{}
/*!
\brief Returns the current state : only valid in the RT reader thread
*/
T* ReadCurrentState()
{
return &fState[GetIndex1(fCounter, 0)];
}
/*!
\brief Returns the current switch counter
*/
UInt16 GetCurrentIndex()
{
return GetIndex1(fCounter, 3);
}
/*!
\brief Tries to switch to the next state and returns the new current state (either the same as before if case of switch failure or the new one)
*/
T* TrySwitchState(int state)
{
AtomicArrayCounter old_val;
AtomicArrayCounter new_val;
do {
old_val = fCounter;
new_val = old_val;
if (GetIndex1(new_val, state)) { // If state has been written
SetIndex1(new_val, 0, SwapIndex1(new_val, state)); // Prepare switch
SetIndex1(new_val, state, 0); // Invalidate the state "state"
IncIndex1(new_val, 3); // Inc switch
}
} while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
return &fState[GetIndex1(fCounter, 0)]; // Read the counter again
}
/*!
\brief Tries to switch to the next state and returns the new current state (either the same as before if case of switch failure or the new one)
*/
T* TrySwitchState(int state, bool* result)
{
AtomicArrayCounter old_val;
AtomicArrayCounter new_val;
do {
old_val = fCounter;
new_val = old_val;
if ((*result = GetIndex1(new_val, state))) { // If state has been written
SetIndex1(new_val, 0, SwapIndex1(new_val, state)); // Prepare switch
SetIndex1(new_val, state, 0); // Invalidate the state "state"
IncIndex1(new_val, 3); // Inc switch
}
} while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
return &fState[GetIndex1(fCounter, 0)]; // Read the counter again
}
/*!
\brief Start write operation : setup and returns the next state to update, check for recursive write calls.
*/
T* WriteNextStateStart(int state)
{
bool tmp;
UInt32 index = WriteNextStateStartAux(state, &tmp);
return &fState[index];
}
T* WriteNextStateStart(int state, bool* result)
{
UInt32 index = WriteNextStateStartAux(state, result);
return &fState[index];
}
/*!
\brief Stop write operation : make the next state ready to be used by the RT thread
*/
void WriteNextStateStop(int state)
{
WriteNextStateStopAux(state);
}
};
} // end of namespace
#endif
/*
Copyright (C) 2004-2006 Grame
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.
*/
#ifndef __JackAtomicState__
#define __JackAtomicState__
#include "JackAtomic.h"
#include <string.h> // for memcpy
namespace Jack
{
/*!
\brief Counter for CAS
*/