Juce on amd64 X2


#1

What’s ther status of juce running on an amd64? I’m running the latest alsa on gentoo with a dual-core amd64. Thanks!


#2

There’s a few bits of inline assembly that won’t work, but apart from that it’s all 64-bit compliant. I’ve not got a 64 bit system myself to try, but if you wanted to have a go and see what errors you get, I’d be happy to help work it out. There’s another 64-bit thread about this kind of thing in the Windows forum today too.


#3

running demo/build/linux/build/jucedemo from 1.34 with gdb I get the following:

________@______ ~/libs/juce/demo/build/linux/build $ gdb jucedemo
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/______/libs/juce/demo/build/linux/build/jucedemo
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 14363)]
JUCE v1.34

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 14363)]
0x000000000051cb99 in noCpuId () at juce_linux_SystemStats.cpp:110
110             *familyModel = family;
(gdb)  

After seeing crashes with 1.34 I tried 1.37 and got the following error:

uce_CharacterFunctions.cpp
../../src/juce_core/text/juce_CharacterFunctions.cpp: In static member function `static int juce::CharacterFunctions::vprintf(char*, int, const char*, const __va_list_tag (&)[1])':
../../src/juce_core/text/juce_CharacterFunctions.cpp:583: error: invalid conversion from `const __va_list_tag*' to `__va_list_tag*'
../../src/juce_core/text/juce_CharacterFunctions.cpp:583: error:   initializing argument 4 of `int vsnprintf(char*, size_t, const char*, __va_list_tag*)'
../../src/juce_core/text/juce_CharacterFunctions.cpp: In static member function `static int juce::CharacterFunctions::vprintf(juce::juce_wchar*, int, const juce::juce_wchar*, const __va_list_tag (&)[1])':
../../src/juce_core/text/juce_CharacterFunctions.cpp:599: error: invalid conversion from `const __va_list_tag*' to `__va_list_tag*'
../../src/juce_core/text/juce_CharacterFunctions.cpp:599: error:   initializing argument 4 of `int vswprintf(wchar_t*, size_t, const wchar_t*, __va_list_tag*)'
make[1]: *** [../../bin/intermediate_linux/Debug/juce_CharacterFunctions.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [JUCE] Error 2

my man pages show the following:

       int vsnprintf(char *str, size_t size, const char *format, va_list ap);

       int vswprintf(wchar_t *wcs, size_t maxlen,
                      const wchar_t *format, va_list args);
~ $ uname -a
Linux tulkas 2.6.15-gentoo-r5 #1 SMP PREEMPT Tue Jul 18 11:57:24 AKDT 2006 x86_64 AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ GNU/Linux

#4

Ok, have a go with this simpler version of the function…

[code]static juce_noinline unsigned int getCPUIDWord (int* familyModel, int* extFeatures)
{
unsigned int cpu = 0;
unsigned int ext = 0;
unsigned int family = 0;
unsigned int dummy = 0;

__asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1));

if (familyModel != 0)
    *familyModel = family;

if (extFeatures != 0)
    *extFeatures = ext;

return cpu;

}
[/code]

And that’s annoying about the vsprintf needing a non-const operand - I guess the fix will just be to make the args parameter non-const.


#5

the new getCPUIDWord compiles and runs on 1.34 but doesn’t like my alsa device.

JUCE v1.34
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
ALSA error: Invalid argument

The new getCPUIDWord compiles fine on 1.37 but ithe demo crashes with the following:

GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/patrick/juce/demo/build/linux/build/jucedemo 
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 7689)]
JUCE v1.37
[New Thread 32769 (LWP 7692)]
[New Thread 16386 (LWP 7693)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 7689)]
0x000000000042feee in juce::atomicIncrement (variable=@0x2aaaad0ba010)
    at juce_Atomic.h:62
62                  : "c" (&variable));
(gdb) quit

FYI: If I remove the const declarations of ‘args’ from all appropriate functions juce 1.37 compiles fine.


#6

That crash is very odd - the atomic.h stuff is exactly the same in both versions. Must be something else causing the error - got a stack trace for it?


#7
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/----------/juce/demo/build/linux/build/jucedemo 
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 11201)]
JUCE v1.37
[New Thread 32769 (LWP 11204)]
[New Thread 16386 (LWP 11205)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 11201)]
0x000000000042feee in juce::atomicIncrement (variable=@0x2aaaad601a60) at juce_Atomic.h:62
62                  : "c" (&variable));
(gdb) bt 100
#0  0x000000000042feee in juce::atomicIncrement (variable=@0x2aaaad601a60) at juce_Atomic.h:62
#1  0x000000000042ad1c in String (this=0x2aaaad601aa0, other=@0x7fffffa17cb0) at juce_String.cpp:156
#2  0x00000000004baa25 in Component (this=0x2aaaad601a90, name=@0x7fffffa17cb0) at juce_Component.cpp:153
#3  0x00000000004c708a in Button (this=0x2aaaad601a90, name=@0x7fffffa17cb0) at juce_Button.cpp:65
#4  0x00000000004c9f00 in DrawableButton (this=0x2aaaad601a90, name=@0x7fffffa17cb0, buttonStyle=juce::DrawableButton::ImageFitted) at juce_DrawableButton.cpp:54
#5  0x0000000000510ea1 in juce::LookAndFeel::createTabBarExtrasButton (this=0x7903c8) at juce_LookAndFeel.cpp:1754
#6  0x0000000000511810 in juce::LookAndFeel::createToolbarMissingItemsButton (this=0x7903c8) at juce_LookAndFeel.cpp:1832
#7  0x00000000004ea773 in Toolbar (this=0x2aaaad600bd0) at juce_Toolbar.cpp:279
#8  0x000000000041b610 in ToolbarDemoComp (this=0x2aaaad600ac0, commandManager=0x7aa590) at WidgetsDemo.cpp:625
#9  0x000000000041a161 in DemoTabbedComponent (this=0x7afdc0, commandManager=0x7aa590) at WidgetsDemo.cpp:916
#10 0x0000000000419dc7 in WidgetsDemo (this=0x7af1e0, commandManager=0x7aa590) at WidgetsDemo.cpp:1029
#11 0x0000000000419890 in createWidgetsDemo (commandManager=0x7aa590) at WidgetsDemo.cpp:1319
#12 0x00000000004086f8 in ContentComp::perform (this=0x790310, info=@0x79bfe0) at MainDemoWindow.cpp:393
#13 0x000000000043ca35 in juce::ApplicationCommandTarget::tryToInvoke (this=0x7903b0, info=@0x79bfe0, async=false) at juce_ApplicationCommandTarget.cpp:66
#14 0x000000000043d090 in juce::ApplicationCommandTarget::CommandTargetMessageInvoker::handleMessage (this=0x7acb70, message=@0x79d6b0)
    at juce_ApplicationCommandTarget.cpp:203
#15 0x0000000000454fbf in juce::MessageManager::deliverMessage (this=0x77de00, message=0x79d6b0) at juce_MessageManager.cpp:111
#16 0x0000000000540daa in juce::juce_dispatchNextMessageOnSystemQueue (returnIfNoPendingMessages=false) at juce_linux_Messaging.cpp:362
#17 0x000000000045513a in juce::MessageManager::dispatchNextMessage (this=0x77de00, returnImmediatelyIfNoMessages=false, wasAMessageDispatched=0x0)
    at juce_MessageManager.cpp:150
#18 0x00000000004553cd in juce::MessageManager::runDispatchLoop (this=0x77de00) at juce_MessageManager.cpp:194
#19 0x0000000000439a77 in juce::JUCEApplication::main (commandLine=@0x7fffffa183b0, app=0x77db80) at juce_Application.cpp:216
#20 0x0000000000439ef2 in juce::JUCEApplication::main (argc=1, argv=0x7fffffa18498, newApp=0x77db80) at juce_Application.cpp:296
#21 0x0000000000407b5f in main (argc=1, argv=0x7fffffa18498) at ApplicationStartup.cpp:118
(gdb) 

#8

Once linked with our library juce 1.34 fails to initialize with the following traceback:


GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/----------/ousia/src/gui/tests/test_ousia/test_ousia 
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 7696)]
Qt: gdb: -nograb added to command-line options.
         Use the -dograb option to enforce grabbing.
[New Thread 32769 (LWP 7699)]
[New Thread 16386 (LWP 7700)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 7696)]
0x0000000000417de1 in juce::String::operator= ()
(gdb) bt 100
#0  0x0000000000417de1 in juce::String::operator= ()
#1  0x0000000000476c86 in juce::FreeTypeInterface::enumerateFaces ()
#2  0x00000000004770fd in juce::FreeTypeInterface::FreeTypeInterface ()
#3  0x0000000000475a50 in juce::Font::getDefaultFontNames ()
#4  0x0000000000421868 in juce::initialiseJuce_GUI ()
#5  0x000000000040bfea in OusiaApplication (this=0x7fffffd2a1a0, argc=@0x7fffffd2a1dc, argv=0x7fffffd2a258) at ApplicationStartup.cpp:84
#6  0x000000000040c4df in main (argc=1, argv=0x7fffffd2a258) at ApplicationStartup.cpp:134
(gdb)

#9

Maybe it just can’t do the assembly language instructions in the atomic.h file. I thought the AMD64 was backwards compatible though?


#10

You say asm and I run for the hills. Funny, I’m the interface guy on this project! Maybe I’ll turn my engine guy to this thread.


#11

Something to try is this slightly tidied-up version of the atomic ops. I’m not enough of a cpu expert to know if this’ll help or not though…

[code] //==============================================================================
/** Increments an integer in a thread-safe way. */
forcedinline void atomicIncrement (int& variable) throw()
{
asm volatile (
“lock incl %0”
: “=m” (variable)
: “m” (variable));
}

/** Increments an integer in a thread-safe way and returns the incremented value. */
forcedinline int atomicIncrementAndReturn (int& variable) throw()
{
    int result;

    __asm__ __volatile__ (
        "lock xaddl %%eax, (%%ebx)  \n\
         incl %%eax"
        : "=a" (result)
        : "b" (&variable), "a" (1)
        : "cc", "memory");

    return result;
}

/** Decrememts an integer in a thread-safe way. */
forcedinline void atomicDecrement (int& variable) throw()
{
    __asm__ __volatile__ (
        "lock decl %0"
        : "=m" (variable)
        : "m" (variable));
}

/** Decrememts an integer in a thread-safe way and returns the incremented value. */
forcedinline int atomicDecrementAndReturn (int& variable) throw()
{
    int result;

    __asm__ __volatile__ (
        "lock xaddl %%eax, (%%ebx)  \n\
         decl %%eax"
        : "=a" (result)
        : "b" (&variable), "a" (-1)
        : "cc", "memory");

    return result;
}[/code]

#12

the patch for juce-1.34 seems to work ok, but I still get an “Invalid argument” error when the juce demo tries to open my audio device (it works elsewhere just fine). Maybe some more debugging info so I can try to fix the problem?

JUCE v1.34
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
ALSA error: Invalid argument

Also, it seems that you including the previous juce_Atomic.h patch in 1.38, and I am seeing the following seg fault when trying to run the demo for 1.38:

GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/patrick/juce/demo/build/linux/build/jucedemo
[Thread debugging using libthread_db enabled]
[New Thread 47562329083024 (LWP 12292)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47562329083024 (LWP 12292)]
0x000000000055aa46 in juce::atomicIncrementAndReturn (variable=@0x7fffb50002dc)
    at juce_Atomic.h:83
83                   : "cc", "memory");
(gdb) bt 100
#0  0x000000000055aa46 in juce::atomicIncrementAndReturn (
    variable=@0x7fffb50002dc) at juce_Atomic.h:83
#1  0x000000000055a91a in juce::initialiseJuce_NonGUI ()
    at juce_SystemStats.cpp:64
#2  0x000000000043d31e in juce::initialiseJuce_GUI ()
    at juce_Application.cpp:310
#3  0x000000000043d656 in juce::JUCEApplication::main (
    commandLine=@0x7fffb5000470, app=0x7739f0) at juce_Application.cpp:178
#4  0x000000000043dc64 in juce::JUCEApplication::main (argc=1,
    argv=0x7fffb50005c8, newApp=0x7739f0) at juce_Application.cpp:296
#5  0x0000000000407b5f in main (argc=1, argv=0x7fffb50005c8)
    at ApplicationStartup.cpp:166
(gdb)

thanks for your help, I can’t wait to get this running so I can develop on my linux machine!


#13

If you could find out what’s causing the alsa error, that’d be handy. Maybe put some breakpoints in the lines that print out the error message and catch it in the act?

I’m a bit lost when it comes to 64-bit asm! Anyone out there know a way of writing the atomic adds that’ll work? I found some compiler intrinsics to do it, which are commented out at line 58 of juce_Atomic.h, but not many compiler versions support them…


#14

The function returning the error is snd_pcm_sw_params_set_silence_size().

I changed the appropriate lines in ALSADevice::setParameters() to the following in juce_linux_Audio.cpp:

        if(failed (snd_pcm_sw_params_current (handle, swParams)))
        return false;
        if(failed (snd_pcm_sw_params_set_silence_threshold (handle, swParams, 0)))
           return false;
        if(failed (snd_pcm_sw_params_set_silence_size (handle, swParams, INT_MAX)))
          return false;
        if(failed (snd_pcm_sw_params_set_start_threshold (handle, swParams, samplesPerPeriod)))
          return false;
        if(failed (snd_pcm_sw_params_set_stop_threshold (handle, swParams, INT_MAX)))
          return false;
        if(failed (snd_pcm_sw_params (handle, swParams)))
          return false;

After googling I found that changing the offending line to the following would allow the device to open:

        if(failed (snd_pcm_sw_params_set_silence_size (handle, swParams, 0)))
          return false;

This worked for some people (notably winemm) , because the silence threshold was zero. All I got was a broken pipe:

JUCE v1.34
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
testing ALSA device: hw:CK804,0 outs=2-6 ins=2-2 rates=2
testing ALSA device: hw:CK804,1 outs=0-0 ins=2-2 rates=1
testing ALSA device: hw:CK804,2 outs=2-2 ins=0-0 rates=1
ALSA error: Broken pipe

#15

The ALSA docs say this:

[quote]Set silence size inside a software configuration container.

Parameters:
pcm PCM handle
params Software configuration container
val Silence size in frames (0 for disabled)

Returns:
0 otherwise a negative error code

A portion of playback buffer is overwritten with silence when playback underrun is nearer than silence threshold (see snd_pcm_sw_params_set_silence_threshold)

The special case is when silence size value is equal or greater than boundary. The unused portion of the ring buffer (initial written samples are untouched) is filled with silence at start. Later, only just processed sample area is filled with silence. Note: silence_threshold must be set to zero. [/quote]

  • a beautiful example of why programmers shouldn’t be allowed to write documentation. If anyone can actually understand what this function does, I’d love to hear it.

Otherwise, I reckon you should just pass in INT_MAX but just carry on if it fails. So just do this:

if(failed (snd_pcm_sw_params_current (handle, swParams))) return false; if(failed (snd_pcm_sw_params_set_silence_threshold (handle, swParams, 0))) return false; snd_pcm_sw_params_set_silence_size (handle, swParams, INT_MAX)); if(failed (snd_pcm_sw_params_set_start_threshold (handle, swParams, samplesPerPeriod))) return false; if(failed (snd_pcm_sw_params_set_stop_threshold (handle, swParams, INT_MAX))) return false; if(failed (snd_pcm_sw_params (handle, swParams))) return false;

or maybe INT_MAX is different on your 64-bit machine? Could always try using 0x3fffffff, as a safer value.[/quote]


#16

yeah, I still get the broken pipe error after that. Sorry, I’m don’t know the alsa api that well.


#17

I’m a bit stuck then. Which line causes the broken pipe error?


#18

I’m not sure what happened, but the code suddenly seems to work. We should assume that it was something on my end until then. I still get the broken pipe line, but the audio is very scratchy in the demo and our app. Also, the demo crashed at one point.

I don’t have the time at the moment to debug it, but at least I gave you some runtime info for linux on amd64 X2. I’ll keep you informed…


#19

the demo from juce 1.39 doesn’t run. I’m getting that same backtrace as before:

0x00000000005624ca in juce::atomicIncrementAndReturn (variable=@0x7fff93e7e2dc)
    at juce_Atomic.h:83
83                  : "cc", "memory");

#20

I’m stuck for ideas. Strange that it used to work, because I don’t think I changed anything in there, and it’s pretty straightforward code.