<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jcm&#039;s blog</title>
	<atom:link href="http://www.jonmasters.org/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jonmasters.org/blog</link>
	<description>World Organi[sz]ation Of Broken Dreams</description>
	<lastBuildDate>Wed, 26 Dec 2012 07:23:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Les Misérables (2012 movie) review</title>
		<link>http://www.jonmasters.org/blog/2012/12/26/les-miserables-2012-movie-review/</link>
		<comments>http://www.jonmasters.org/blog/2012/12/26/les-miserables-2012-movie-review/#comments</comments>
		<pubDate>Wed, 26 Dec 2012 07:19:49 +0000</pubDate>
		<dc:creator>jcm</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.jonmasters.org/blog/?p=1166</guid>
		<description><![CDATA[I saw the new Les Misérables movie this evening. I was more than impressed. Hooper did a magnificent job directing (the all close-up style as ]]></description>
			<content:encoded><![CDATA[<p>I saw the new Les Misérables movie this evening. I was more than impressed. Hooper did a magnificent job directing (the all close-up style as <a href=http://www.nytimes.com/2012/12/23/movies/les-miserables-on-film-cameron-mackintoshs-dream.html?pagewanted=all&#038;_r=0">discussed by the New York Times</a> does actually enhance the experience, and does grow on you during the course of the movie), while the all star cast was phenomenal. In particular, Russell Crowe was outstanding as Inspector Javert, perfectly portraying his blind enforcement of the law, as well as his later epiphany. I would say Javert, in particular, is better played on screen by Crowe than in the live stage performance I have seen. Overall I really loved this movie. Les Mis. is one of my all-time favorite musicals, and I know most of the songs from memory. I sadly also fancy that I have reluctantly played the role of Eponine (ever unrequited) more often in my life than either of Marius or Cosette, which is perhaps why I find the story so moving. The new movie adaptation has inspired me, and I shall most likely see the live version again when next I am in London.</p>
<p>Hugh Jackman is an excellent Jean Valjean, convincingly portraying the turned-to-the-light Frenchman who is ever in the right. Eddie Redmayne is a solid Marius Pontmercy, while Amanda Seyfried is a convincing Cosette (whose role is always surprisingly smaller than you would expect). I enjoyed Samantha Barks as Eponine. Her delivery of &#8220;On My Own&#8221; was excellent. I much preferred that to Hathaway&#8217;s &#8220;I Dreamed a Dream&#8221;, but that piece has so much to live up to that it&#8217;s hard to be outstanding any more. Hathaway provided an outstanding performance otherwise. Crowe and Jackman nearly steal the show as far as vocal performance, with the exception of Seyfried, who was also excellent. Both Daniel Huttlestone (the boy urchin) and Isabelle Allen (the young Cosette) are adorably good. I was not as impressed with Helena Bonham Carter and Sacha Baron Cohen. While they were solid performances, I was left wondering whether they were cast more for the benefit of audience entertainment (in which the reaction was anticipated &#8211; audience laughter did greet them on several occasions).</p>
<p>Overall, this adaptation is excellent. You should see it, even if you have not seen it performed on stage. But a point of housekeeping. Please stay at home if you are not interested in enjoying the movie, or appreciating the story. If you&#8217;d rather be playing a video game or watching MTV, don&#8217;t be the guy who fell asleep and snored in the theater during the performance this evening, or the countless others who couldn&#8217;t keep quiet for a couple of hours. The cultural experience was largely lost on them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonmasters.org/blog/2012/12/26/les-miserables-2012-movie-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ARM atomic operations</title>
		<link>http://www.jonmasters.org/blog/2012/11/13/arm-atomic-operations/</link>
		<comments>http://www.jonmasters.org/blog/2012/11/13/arm-atomic-operations/#comments</comments>
		<pubDate>Tue, 13 Nov 2012 05:11:32 +0000</pubDate>
		<dc:creator>jcm</dc:creator>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Fedora]]></category>

		<guid isPermaLink="false">http://www.jonmasters.org/blog/?p=1156</guid>
		<description><![CDATA[Edit: I&#8217;ve fixed parts of the atomic addition example following feedback from Nicolas Pitre. There were a couple of things that were just sloppy 4am stuff on my part, and a couple from just trying to be too much like the rest of the OpenMPI code. I&#8217;ve cleaned up the example and re-tested.
Modern 32-bit ARM [...]]]></description>
			<content:encoded><![CDATA[<p><b>Edit</b>: I&#8217;ve fixed parts of the atomic addition example following feedback from Nicolas Pitre. There were a couple of things that were just sloppy 4am stuff on my part, and a couple from just trying to be too much like the rest of the OpenMPI code. I&#8217;ve cleaned up the example and re-tested.</p>
<p>Modern 32-bit ARM processors are becoming increasingly more complex than was the case with the implementation of previous generations of the architecture. Processors implementing version 5 of the architecture do not support Symmetric Multi-Processing (SMP), while newer architecture versions add not only full capability for SMP (and its related supporting architectural extensions), but even go as far as to enable the implementation of designs based upon AMP (Assymmetric Multi-Processing[0]) &#8211; commonly known as Big.LITTLE. These newer features require changes to the underlying architecture, to support memory ordering operations, cache coherent access to shared memory, atomic operations, and so on. This article summarizes some of these changes, with a view toward Fedora developers needing to modify ARM code, especially to implement support for atomic operations. Much greater documentation is available online, especially on ARM&#8217;s own website.</p>
<p>Whenever multiple processor cores will share physical access to system memory, there is a need to be concerned with unintended interactions between those processors. Fundamental Computer Science principals teach us about the importance of atomicity (and we will come to that) but there are deeper and more complex interactions that must be considered when introducing SMP, as ARMv6 did. Not only is the atomicity of operations important, but so is the ordering of their visibility to other processors. Modern CPUs execute instructions speculatively (meaning they may or may not actually take effect, based upon predicted-taken branches or the interaction of exceptions, and so on), out-of-order (meaning operations may not strictly occur always in program order &#8211; the visible impact of this upon program execution depends upon various other factors), and may not have the same guarantees concerning visibility of these operations that programmers familiar with older architectures have come to expect.</p>
<p>In essence, ARM makes a number of tradeoffs in the interest of optimal performance (and lower energy). As a weakly ordered memory architecture, a local ARM processor core guarantees only self-consistent ordering of program operations. That is, the executing program will appear to manipulate external memory in strict program order only from the point of view of the local processor. External viewers (processors or devices) that independently observe the actions of the processor may see the effects of load and store re-ordering or other microarchitectural optimizations that are normally hidden in the non-SMP case. Thus one drawback of being weakly ordered is that the processor must be explicitly informed of memory dependencies that it cannot automatically determine. The outcome of a memory operation may otherwise be sitting in a CPU drain buffer waiting to be written back to memory (and thus the altered content is only visible to code running on the local processor node), may be sitting in a local cache within a CPU or CPU cluster (and thus visible only to a subset of processors), or may be sitting in an L2 cache that has yet to hit physical memory, among many other possibilities.</p>
<p>To ensure that a specific memory operation has completed in program order prior to the execution of subsequent operations, memory barriers are inserted. These instruct the CPU microarchitecture to ensure the result of certain prior memory operations (in terms of program order) have been fully committed back to system memory, or at least as far as the system cache configuration will guarantee to be the case for the specific operation. Memory barriers don&#8217;t ensure that another CPU cannot interfere with the value in memory (they are not an atomicity guarantee) but they do serve to ensure that actions occur in a defined known order. For example, writing to device memory configuration registers requires a memory barrier in order to ensure that the write has been fully completed.</p>
<p>ARMv7 provides three forms of memory barrier:</p>
<ul>
<li>DMB (Data Memory Barrier)</li>
<li>DSB (Data Synchronization Barrier)</li>
<li>ISB (Instruction Synchronization Barrier)</li>
</ul>
<p>The first, DMB, ensures that all explicit memory operations have completed. It can be used to ensure that a memory store has taken effect. By default, it performs a &#8220;system&#8221; DMB operation &#8211; a full memory barrier. This can also be specified through the optional parameter &#8220;SY&#8221; to the DMB instruction, but it is assumed as the default if omitted. DMB supports several other options, including &#8220;ST&#8221; (wait only for stores), and various others pertaining to the extent of shareability domains that will be omitted here for simplification (extensive documentation exists). If in doubt, a “DMB” operation without a parameter is the strongest and safest.</p>
<p>The second and third memory barrier operations are related. DSB ensures that all instructions before the DSB have completed (with optional parameters similar to the DMB operation), while the ISB <strike>does a full system level DSB but also</strike> ensures that the CPU pipeline is completely flushed and all instructions reloaded. ISB is used in self modifying code sequences to ensure that the new code is executed. It technically has an option, but that can only be &#8220;SY&#8221;.</p>
<p>Memory barriers of this form were first introduced in ARMv6, where they are actually implemented as control register writes into the cp15 (co-processor number 15, the VMSA memory management control co-processor in the 32-bit ARM architecture, not present in the 64-bit ARMv8 architecture). ARM have now deprecated this approach in favor of specific ISA extensions in ARMv7, but for reasons of backward compatibility, these cp15 writes are still supported:</p>
<ul>
<li>DMB: MCR p15, 0, r0, c7, c10, 5</li>
<li>DSB: MCR p15, 0, r0, c7, c10, 4</li>
<li>ISB: MCR p15, 0, r0, c7, c5, 4</li>
</ul>
<p>ARMv7 simply requires use of the &#8220;DMB&#8221;, &#8220;DSB&#8221;, or &#8220;ISB&#8221; instructions for memory barrier insertion. An example of their implementation can be found in the OpenMPI Fedora package, within the opal/include/opal/sys/arm/atomic.h C language header include file, that contains the following usage on ARMv7:</p>
<pre>
#define MB()  __asm__ __volatile__ ("dmb" : : : "memory")
#define RMB() __asm__ __volatile__ ("dmb" : : : "memory")
#define WMB() __asm__ __volatile__ ("dmb" : : : "memory")
</pre>
<p>And the following usage on ARMv6 systems:</p>
<pre>
#define MB()  __asm__ __volatile__ ("mcr p15, 0, r0, c7, c10, 5" : : : "memory")
#define RMB() MB()
#define WMB() MB()
</pre>
<p>The reader may wonder whether there is a need for memory barriers on ARMv5 systems. The answer is that there is such a need because the kernel provided emulated atomic operations (explained further below) assume that calls to dmb are being made as is required architecturally following certain other operations (and may perform its own context synchronizing operations within the helper). The ARM Linux kernel provides __kuser_helpers for emulation of missing features on older CPUs. They behave as if they were VDSOs (Virtual Dynamic Shared Objects) – which are effectively shared libraries provided automatically by the kernel for every running process &#8211; but they are not full VDSOs on 32-bit ARM systems.</p>
<p>To use the __kuser_memory_barrier helper operation, which will do the right thing no matter the version of the ARM architecture, one need only have a kernel version higher than that providing __kuser_helper_version 3 (which was 2.6.15) and then define a function as follows (an OpenMPI example):</p>
<pre>
#define MB() (*((void (*)(void))(0xffff0fa0)))()
</pre>
<p>Calls to MB() will result in a call to a void function provided directly by the kernel within the process memory map, as if it were a library.</p>
<p>Barriers are useful for program correctness in weakly ordered systems, but they are not sufficient to provide atomicity guarantees of the kind needed to implement atomic operations. To provide for atomic access to a given memory location, ARM processors implement a reservation engine model. A given memory location is first loaded using a special &#8220;load exclusive&#8221; instruction that has the side-effect of setting up a reservation against that given address in the CPU-local reservation engine. When the modified value it is later written back into memory, using the corresponding &#8220;store exclusive&#8221; processor instruction, the reservation engine verifies that it has an outstanding reservation against that given address, and furthermore confirms that no external agents have interfered with the memory commit. A register returns success or failure.</p>
<p>The CPU can typically have only one outstanding reservation at a given time (so a load-exclusive must be typically followed shortly by a corresponding store-exclusive &#8211; typical of a lock implementation or atomic variable access implementation for which it was created), and it will flush outstanding reservations at context switch time. This means that a load-exclusive/store-exclusive pair may fail and be require repeated attempts until it is successful. Thus, a small loop is typically utilized, with the &#8220;store exclusive&#8221; operation returning a success or fail code in a register, and a comparison before loop on failure.</p>
<p>ARMv6 and later processors implement:</p>
<ul>
<li>lrdex (Load Exclusive)</li>
<li>strex (Store Exclusive)</li>
</ul>
<p>Ldrex is used similarly to &#8220;ldr&#8221;, with the following loading a memory location:</p>
<ul>
<li>ldrex r0, [address]</li>
</ul>
<p>Strex takes an additional parameter over a usual store operation:</p>
<ul>
<li>strex r0, r1, [address]</li>
</ul>
<p>With r0 containing the return result, and r1 containing the value to write back.</p>
<p>These operations are typically used in a tight loop to implement either an atomic variable manipulation routine (such as an increment or decrementation operation), or a local acquisition and reliquishment pair of routines. In the case of OpenMPI, an atomic 32-bit addition is performed as follows on ARMv6+:</p>
<pre>
static inline int32_t opal_atomic_add_32(volatile int32_t* v, int inc)
{
   int32_t t;
   int tmp;

   __asm__ __volatile__(
                         "1:  ldrex   %0, [%2]        \n"
                         "    add     %0, %0, %3      \n"
                         "    strex   %1, %0, [%2]    \n"
                         "    cmp     %1, #0          \n"
                         "    bne     1b              \n"

                         : "=&#038;r" (t), "=&#038;r" (tmp)
                         : "r" (v), "r" (inc)
                         : "cc", "memory");

   return t;
}
</pre>
<p>Notice how the ldrex operation is repeated until the corresponding strex reports that the addition was performed before another processor (or another task &#8211; which causes a flush of all reservations) interferred. As is the case for memory barriers, the ARM Linux kernel provides emulation of such atomic operations in the case that they are not supported by the hardware (on ARMv5 and earlier processors). The kernel-provided __kuser_cmpxchg atomic compare-and-exchange &#8220;helper&#8221; can be used to implement an atomic addition as in the following example, taken from the Documentation/arm/kernel_user_helpers.txt file in the kernel:</p>
<pre>
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)

int atomic_add(volatile int *ptr, int val)
{
        int old, new;

        do {
                old = *ptr;
                new = old + val;
        } while(__kuser_cmpxchg(old, new, ptr));

        return new;
}
</pre>
<p>In the case of OpenMPI, the actual implementation needs to be implemented in assembly code due to the design of the OpenMPI codebase. This is not typical, but is included here in the interest of completenss. Therefore, the following contrived call to the kernel user helper (as in the above much more readible and generally suitable example) is actually performed:</p>
<pre>
START_FUNC(opal_atomic_add_32)
        push    {r4, lr}
        mov     r4, r1
        mov     r2, r0
        LSYM(4)
        ldr     r0, [r2]
        ldr     r3, REFLSYM(5)
        add     r1, r0, r4
        blx     r3
	bcc     REFLSYM(4)
	pop     {r4, lr}
        bx      lr
        .align  2
        LSYM(5)
        .word   0xffff0fc0
END_FUNC(opal_atomic_add_32)
</pre>
<p>The &#8220;START_FUNC&#8221;, &#8220;END_FUNC&#8221;, &#8220;REFLSYM&#8221;, and &#8220;LSYM&#8221; macros are pre-processed (by generate-asm.pl, using data provided by asm-data.txt and other files) during the build to produce code resembling the following:</p>
<pre>
opal_atomic_add_32:
        push    {r4, lr}
        mov     r4, r1
        mov     r2, r0
.L4:
        ldr     r0, [r2]
        ldr     r3, .L5
        add     r1, r0, r4
        blx     r3
        bcc     .L4
        pop     {r4, lr}
        bx      lr
        .align  2
.L5:
        .word   0xffff0fc0
        .align  2
        .global opal_atomic_add_32
        .type   opal_atomic_add_32, %function
</pre>
<p>All this code actually does is to save the r4 and lr registers at function entry (as defined by the ARM Architecture Procedure Calling Standard or AAPCS) before re-organizing the parameters passed in (which are in the ordering specific to OpenMPI&#8217;s internal implementation) into the order needed to call the kernel&#8217;s __kuser_cmpxchg function to perform an atomic swap of the old and newly incremented values. The address of this kernel function is stored in the &#8220;L5&#8243; symbol (0xffff0fc0), and it is used to atomically swap the &#8220;old&#8221; value read into r0 with the incremented value passed in r1. As is the case for most cmpxchg routines, the kernel will return a failure whenever the &#8220;old&#8221; value passed does not match the actual value of the memory prior to manipulation. The kernel is able to use special means to do this compare atomically that non-kernel code on ARMv5 systems cannot do alone, guarding against interference. A result is returned in r0 and compared against an expected zero value. The comparison to zero is actually done by the kernel helper, which sets the &#8220;C&#8221; (carry) condition code accordingly (set if result zero, clear otherwise) prior to returning (saving a subsequent compare operation). If non-zero (carry is clear), the operation is repeated with a conditional (bcc) jump back to the beginning of the atomic add function.</p>
<p>Modifying software to cope simultaneously with older ARM architectures, as well as more modern ones is vastly simplified through the use of compatibility features, such as the __kuser helpers in the ARM Linux kernel. For more information, see the Documentation/arm/kernel_user_helpers.txt file within the Linux kernel source. For examples of use, refer to packages such as OpenMPI, which have already been modified for ARM systems.</p>
<p>[0] Assymmetric Multi-Processing (AMP) &#8211; aka Big.LITTLE &#8211;  uses relatively different performing cores, all ISA compatible, to provide for different performance/power characteristics, depending upon the workload.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonmasters.org/blog/2012/11/13/arm-atomic-operations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>libkmod replaces module-init-tools</title>
		<link>http://www.jonmasters.org/blog/2011/12/20/libkmod-replaces-module-init-tools/</link>
		<comments>http://www.jonmasters.org/blog/2011/12/20/libkmod-replaces-module-init-tools/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 00:16:23 +0000</pubDate>
		<dc:creator>jcm</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.jonmasters.org/blog/?p=1150</guid>
		<description><![CDATA[UPDATE: For more information, consider joining #kmod on Freenode. Development is using the existing linux-modules@vger.kernel.org mailing list.
The team at ProFUSION (and other helpful contributors) have done an awesome job at quickly turning the Plumber&#8217;s Wishlist for Linux kernel module loading library item into reality. libkmod is linkable into udev, will speed up module loading, and [...]]]></description>
			<content:encoded><![CDATA[<p><b>UPDATE</b>: For more information, consider joining #kmod on Freenode. Development is using the existing linux-modules@vger.kernel.org mailing list.</p>
<p>The team at <a href="http://www.profusion.mobi/">ProFUSION</a> (and other helpful contributors) have done an awesome job at quickly turning the <a href="http://lwn.net/Articles/462076/">Plumber&#8217;s Wishlist for Linux</a> kernel module loading library item into reality. <a href="http://git.profusion.mobi/cgit.cgi/kmod.git/">libkmod</a> is linkable into udev, will speed up module loading, and has a stated goal of remaining backward compatible with the existing behaviors already present within module-init-tools. Therefore, the average user should notice nothing other than an improved in module load times in switching to the replacement library. Those features not yet present in libkmod will be added over the coming weeks. The new library could do with some testing on non-x86, bi-endian, and will need some further thoughts around index cacheing (e.g. within long-lived processes), but is ready enough for wider use. To find out more about the library, visit the initial blog posting from the ProFUSION team:</p>
<p><a href="http://www.politreco.com/2011/12/announce-kmod-1/">http://www.politreco.com/2011/12/announce-kmod-1/</a></p>
<p>Jon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonmasters.org/blog/2011/12/20/libkmod-replaces-module-init-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Citizen Journalism</title>
		<link>http://www.jonmasters.org/blog/2011/11/30/on-citizen-journalism/</link>
		<comments>http://www.jonmasters.org/blog/2011/11/30/on-citizen-journalism/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 23:19:02 +0000</pubDate>
		<dc:creator>jcm</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.jonmasters.org/blog/?p=1147</guid>
		<description><![CDATA[We are entering a very dark and dangerous time for humanity. The rise of social media and the mediocre web (in which everyone&#8217;s voice, no matter how uninformed, is equal) can be a very positive change for good. Connecting people in far flung parts of the world allows &#8220;iReports&#8221;, leaks, government suppression, and many other [...]]]></description>
			<content:encoded><![CDATA[<p>We are entering a very dark and dangerous time for humanity. The rise of social media and the mediocre web (in which everyone&#8217;s voice, no matter how uninformed, is equal) can be a very positive change for good. Connecting people in far flung parts of the world allows &#8220;iReports&#8221;, leaks, government suppression, and many other issues to come to light. But at the same time, those who seek the utter demise of traditional media represent some of the most uninformed malignants who will cause great harm to our country, and to the wider world at large.</p>
<p>Traditional news media, like the <a href="http://www.nytimes.com/">New York Times</a> is under constant threat from those who seek its destruction and replacement with mindless crap written in 140 characters or less. Regurgitated opinion of the collective Tweeters of the world will not create media outlets in war zones, or fund researchers to trawl through years of government records. Wikileaks alone will not displace the need for professionally, carefully presented (fair) treatment of horribly offensive abuses of the governments of the world. RSS aggregation of news media and proliferation of links online has been phenomenal in disseminating news and readers such as those available from Google (and others) have presented it well. But all of these news stories ultimately come from somewhere real, somewhere tangible, somewhere less Web 2.0 and more &#8220;real world 1.0&#8243;. Take the Times (and a few others) out of the picture and you&#8217;ll quickly notice the dearth of good quality news sources available for others to regurgitate.</p>
<p>This is why I have two subscriptions to the New York Times. I pay for my quality journalism, and I pay double (or many times more) what some others pay because I care that the United States paper of record remain in business. Those of us who care must band together to disrupt and undermine others who seek to destroy quality journalism and replace it with mediocre populist nonsense of the kind favored by contestants on Reality TV shows. Is this elitist? Absolutely. It is absolutely the case that most people don&#8217;t care about the minitia reported in the Times, about the investigative undercover stories, and about the analysis that goes into them. Most care more about what some famous moron said today or which YouTube video is hot. And that&#8217;s ok. Let them eat cake, and let them enjoy it too. But don&#8217;t take away quality news from those of us who are interested in knowing what&#8217;s really going on in the world.</p>
<p>Jon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonmasters.org/blog/2011/11/30/on-citizen-journalism/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Spotify desktop app</title>
		<link>http://www.jonmasters.org/blog/2011/10/03/spotify-desktop-app/</link>
		<comments>http://www.jonmasters.org/blog/2011/10/03/spotify-desktop-app/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 02:17:23 +0000</pubDate>
		<dc:creator>jcm</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.jonmasters.org/blog/?p=1142</guid>
		<description><![CDATA[I bought a Spotify subscription recently. I like the concept, and the Android app is just about usable (though not an Apple-level application at this point). What is really driving me nuts is that, if you fall into the trap of registering with your Facebook account (they present it as a single-sign-on option, but really [...]]]></description>
			<content:encoded><![CDATA[<p>I bought a Spotify subscription recently. I like the concept, and the Android app is just about usable (though not an Apple-level application at this point). What is really driving me nuts is that, if you fall into the trap of registering with your Facebook account (they present it as a single-sign-on option, but really it&#8217;s to push the integration), Spotify goes into a special obnoxious mode wherein it insists that you always have the app installed in your Facebook account. Changing permissions on the app or removing its ability to post to your account only invites an error &#8211; especially in the second case, wherein it will bug you *every* time you play a track that you don&#8217;t have it in your timeline. Do my friends really care /that/ much about what I&#8217;m listening to that they can&#8217;t choose to follow my last.fm and leave it at that?</p>
<p>I&#8217;ve tried complaining to Spotify, asking how to switch my account to the non-Facebook mode (that hopefully just plays songs, like I paid for). I have heard nothing yet. My next recourse will be to complain to Facebook that Spotify have an app that is malicious and should be removed from the site. I suspect that would then get a customer service reply from Spotify. Not my preferred means to make contact and get this fixed, but certainly an option.</p>
<p>Jon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jonmasters.org/blog/2011/10/03/spotify-desktop-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
