Conditional Operator Harmful ? yes : no

It seems existing versions of gcc don't warn when you use an assignment as a truth value as the first operand to the conditional operator. For example:

int fn(int i)
{
    return (i = 0x20) ? 0x40 : 0x80;
}

Presumably you meant ==, but unfortunately that does not warn with gcc (maybe it will one day).

We can use the tree dumping mechanisms (previously mentioned here) to confirm our problem. For the following function gcc creates:

fn (i)
{
  int D.1541;
  int iftmp.0;

  i = 32;
  if (1)
    {
      iftmp.0 = 64;
    }
  else
    {
      iftmp.0 = 128;
    }
  D.1541 = iftmp.0;
  return D.1541;
}

As you can see, this isn't the result we wanted. This can be quite nasty if you use the conditional operator in a hidden fashion; for example behind an assert. A common idiom is:

#define ASSERT(x) (x) ? : fail()

/* programmer now subsitutes a == for */
ASSERT(x = y);

You'll currently get no warning you've slipped up and used the assert wrong. Moral of the story: a quick audit of your code might turn up some surprising uses! However, in this case, the Intel compiler picks this one up:

$ icc -c test.c
test.c(3): warning #187: use of "=" where "==" may have been intended
       return (i = 0x20) ? 0x40 : 0x80;

Although it's often not trivial to move to another compiler, as a rule I would recommend trying alternative compilers for your code as it's a great sanity check.

Tips and tricks for your E3 Visa

Having recently been through the process, I've managed to come out the other-side with some some advice for anyone taking this on.

  • To start out, the link for making appointments at the Australian Consulate is VisaPoint. I found it was remarkably well hidden.
  • Upon entering the country, it's quite likely the immigration officer won't be that familiar with the E3 Visa. I'd recommend you watch them and very politely correct anything you think wrong, in my case my Visa was incorrectly entered as E3-Dependent along with my wife (proving that the system doesn't actually keep referential integrity between an E3 and an E3D holders).
  • You can not get paid before receiving a social security number. You can not apply for a social security number within about 10 days of entering the country, as there is a lag between immigration and social security systems. Once you apply it will take a few weeks for the card, but you can probably go back to the office with sufficient ID within two days and receive a print-out of the number. You can call the office you filed with first and they can tell you if it's worth coming in to try it. In the absolute worst case, if things screw-up, you could be in for a long wait. Your company may be able to loan you money if things get desperate.
  • If anything really stuffs up you'll have to enter the US immigration services, which is no fun. If this happens to you in the Bay Area go straight to the San Francisco office; the San Jose office doesn't have deferred inspections so you'll probably just have to go there anyway.
  • Your dependent on the E3D Visa will need to fill out an I-765 work authorisation form. This will take up to 3 months to process; you can find out the approximate queue time here. The form doesn't appear to have been updated for E3D; I would strongly recommend getting a lawyer to file it for you so you don't stuff it up. Budget about $400. After this has been processed, the dependent will then need to file for a SSN before they can be paid.
  • Tax is a black-art. In California expect to pay something like 20-25% federal, 10% state and up to 7% more for Medicare and social security. Expect another $80/month for health insurance.
  • You can get a bank account without a SSN easily. A good way to transfer money is OzForex, but watch out for fees on the US side (you may have to do wire-transfers which cost about $10 a go, though some banks have bill-pay). The country still runs on cheques for some reason.
  • You can rent without a SSN, but it will cost you. Budget for 2 months extra rent as deposits and paying ahead.
  • A car lease is probably a good way to go. Finance will usually look at your visa and only give you a two-year loan, and with no credit that will be at a very high interest rate. In California you can get a 2 year lease on a base model new car (sticker price ~$17,000) drive-away for a down-payment of about $2500 and then $250/month plus taxes. Insurance will be about $120/month on-top of that. The beauty is you just give it back when you go home. For long holiday trips SUV rental may contribute to global warming, but is a very comfortable way to see the country.
  • In California you'll need to book in for a driving test to get a license; you can't do this in a rental car but some local driving schools offer a short introduction course and then let you use their car for the test.
  • If you're living in temporary accommodation without great facilities Dream Dinners is a good way to easily get some meals together.
  • In the Bay Area, Yelp is an awesome resource.
  • Comcast make Telstra look like a well-run, efficient and customer focused organisation!

Feel free to drop me a line if you're thinking of taking an opportunity and have any questions.

Grace Wifi Radio Review

I recently purchased a Grace ITC-IR1000 Wifi Radio from Beach Audio.

Grace ITC-IR1000 Wifi Radio

There seem to be a number of competing products available at the moment, and it seems they are all based on the Reciva internet radio platform. This appears to be an ARM based system running Linux (checkout the GPL compliance area).

It has built-in wireless, so connects up directly to your 802.11 network. It supports WEP and WPA; entering the WPA key is a little like entering your high score on an arcade game with a built-in scrolling alphabet. It supports all sorts of codecs, including the most important Real, WMA and MP3.

Once on the network, it contacts Reciva service (free) to update and download channel lists. Once there, you can select stations filtered by region (Europe, Oceania, etc) then country. There are literally thousands to choose from, and users can contribute streams which are filtered by Reciva and added to the database periodically. An excellent feature is the ability to log-in to the website and both build favourite lists and add your own personal streams. You then register your radio's serial number with the website and on the next channel update you get access to your lists.

It also offers you the opportunity to connect to a local PC to stream music from folders there; I haven't looked into this feature at all.

Overall, it's a great device. The audio quality is great, and it seems to have at least a little sub-woofer built in. It has some nice features; 5 of the buttons on the front are quick access preset buttons, just hold it down when you are listening to the station and it remembers it. It supports a wide range of streams, the interface is simple to understand, it keeps the clock via NTP and directly connecting to the wireless is great.

My ideal application is for a bedside clock radio, so I can listen to .au radio as I go to sleep and wake up. It has an inbuilt back-lit clock, sleep timer and alarm system, but they all take a bit of fiddling. The buttons are small and black, which doesn't help in the dark, and most access is done via the big scroll wheel which you press to make a selection (think iPod). However, the resistance of the rubber pads is less than that the pressure required to push the button in, so it really takes two hands. This means when you want to setup an alarm and put on the sleep timer as you go to bed there is a bit of fiddling through menus, etc. Also, as it is playing the clock seems to go away. Initially I had a problem with firewall ports, but it doesn't seem a big issue on the forums so it must have just been me.

I also wonder what happens when Reciva go out of business, because all the tuning happens via their website. Something similar happened when 3com Audrey support was dropped; it then became a matter of faking DNS replies. Sniffing the protocol might be fun :)

All in all, although it sounds a little silly, if you know what you want it for this is a great little system. I imagine any expat will get their money's worth listening to home radio stations. If you're only interested in local radio, I'd still suggest the best thing is still probably (surprise, surprise) a radio. It leaves a little to be desired as a bedside radio but is otherwise a very nice toy!

2009-02-20 This has turned out to be one of the more popular things I have ever posted, so I should provide an update. There have been several firmware updates released with a range of new features, the most notable being able to hook up to Pandora and Sirius.

Other than that, there have been some nice updates such as allowing the wireless to stay connected in the background, reducing the time between turning on and getting radio sounds out, and a few display updates like displaying the time while radio is playing.

I have played around a bit more with the local media streaming; I found it quite unintuitive and difficult to use. I set up my entire MP3 collection as a Samaba share and pointed the radio at it, but it choked scanning the directory and the few thousand files. I found the only practical way was to setup a separate share with just a few things in it and create a .m3u playlist. Trying to navigate through many songs on the little screen just isn't great.

Setting up an iPhone via prepay

Just a quick note for Google on setting up a newly purchased iPhone on an AT&T GoPhone pre-pay plan, rather than the contract plan. Although the plans kind of suck, you might like to do this if you don't have a social security number or credit history.

Several forums mention using an all-9's SSN or an all 1's SSN in the signup field. As of 4th March, 2008, these are not working. You need a different SSN which can be provided by AT&T (a hint, it has a lot of 1's and a 4, although I get the feeling they change this as too many people discover it). This will have the effect of failing the credit check, and even though you have to go through and agree to all the contract terms it will then present you with prepay options.

Hopefully that saves some people time setting up their new iPhone!

Forwarding VNC via ssh, or finding the PID of a running ssh

I found a few people asking how to automate scripts using ssh with the -f option but not many solutions. Th -f option makes the ssh process fork into the background once started, but since it doesn't give you it's PID it becomes hard to kill it once the script ends.

The solution is to setup a control channel with -M. This allows you to communicate to the ssh process and close it down when your process finishes. For example, here is how I open a VNC connection to my desktop at work, which involves going through a corporate ssh firewall box.

ssh -M -S /tmp/vncssh-firewall.ctl -L 2022:desktop.internal.company.com:22 -f -N username@firewall.company.com
ssh -M -S /tmp/vncssh-localhost.ctl -N -p 2022 -L 5901:localhost:5901 -f -N username@localhost
xtightvncviewer -encodings tight localhost:1
ssh -S /tmp/vncssh-firewall.ctl -O exit localhost
ssh -S /tmp/vncssh-localhost.ctl -O exit firewall.company.com

How not to move an iTunes library

I now have several tips on how not to move an iTunes library from a Windows machine to a Mac. The presmise is simple; firstly request iTunes consolidate the library on the source machine and then move the c:\Documents and Settings\username\My Music\iTunes folder to ~/Music/iTunes on the Mac.

So, what I would reccommend not to do:

  • Simply copy the iTunes directory from an NTFS partition to a FAT formatted media. Somewhere between there and OSX I found special and unicode characters in the filenames got lost. Theoretically maybe this should work, but it didn't.
  • Attempt to be "unixy" and use a Windows tar utility to a FAT disk. FAT only supports files less than 4GiB.
  • Re-format the external media as NTFS and then use a Windows tar utility. Untarring on OSX resulted in even more screwed up filenames.
  • Moving via samba/NFS

What I would recommend is using the 7-Zip utility to create an uncompressed archive of the directory on a NTFS formatted disk (for large file sizes) and then unarchiving it on OSX at the other end. This reliably handled all the crazy file names and the migrated library works perfectly.

CDBS and .install files

Last night, after dropping a package from a control file, I was wondering why my package.install file for the remaining package seemed to be ignored (upstream installs a bunch of stuff that I don't want installed in the Debian package; the symptom was all that junk was making its way into the package). Turns out it comes down to the following logic in CDBS:

ifeq ($(words $(DEB_ALL_PACKAGES)),1)
        DEB_DESTDIR = $(CURDIR)/debian/$(strip $(DEB_ALL_PACKAGES))/
else
        DEB_DESTDIR = $(CURDIR)/debian/tmp/
endif

i.e. if there is only one package, then by default install in debian/package. Therefore whatever make install does is what you end up with in your package. Although I can see the reasoning behind this, it wasn't what I wanted since I need the package installed into a temporary location (i.e. debian/tmp) which then uses a .install file to pull out only those files I want. The solution is simple, override DEB_DESTDIR to $(CURDIR)/debian/tmp/ in rules.

I hope this saves someone the half hour or so I spent investigating why my install file was "corrupt"!

Compare and Swap with PIC

Our Dear Leader Sam Hocevar has previously blogged about PIC and inline ASM. Today I came across a sort of extension to this problem.

Consider the following code, which implements a double word compare and swap using the x86 cmpxchg8b instruction (for a bonus you can lock it to make it atomic).

#include <stdio.h>

typedef struct double_word_t {
    int a;
    int b;
} double_word;

/* atomically compare old and mem, if they are the same then copy new
   back to mem */
int compare_and_swap(double_word *mem,
             double_word old,
             double_word new) {

    char result;
    __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;"
                 : "=m"(*mem), "=q"(result)
                 : "m"(*mem), "d" (old.b), "a" (old.a),
                   "c" (new.b), "b" (new.a)
                 : "memory");
    return (int)result;
}

int main(void)
{

    double_word w = {.a = 0, .b = 0};
    double_word old = {.a = 17, .b = 42};
    double_word new = {.a = 12, .b = 13};

    /* old != w, therefore nothing happens */
    compare_and_swap(&w, old, new);
    printf("Should fail -> (%d,%d)\n", w.a, w.b);

    /* old == w, therefore w = new */
    old.a = 0; old.b = 0;
    compare_and_swap(&w, old, new);
    printf("Should work  -> (%d,%d)\n", w.a, w.b);

    return 0;
}

This type of CAS can be used to implement lock-free algorithms (I've previously blogged about that sort of thing).

The problem is that the cmpxchg8b uses the ebx register, i.e. pseudo code looks like:

if(EDX:EAX == Destination) {
    ZF = 1;
    Destination = ECX:EBX;
}
else {
    ZF = 0;
    EDX:EAX = Destination;
}

PIC code reserves ebx for internal use, so if you try to compile that with -fPIC you will get an error about not being able to allocate ebx.

A first attempt to create a PIC friendly version would simply save and restore ebx and not gcc anything about it, something like:

__asm__ __volatile__("pushl %%ebx;"   /* save ebx used for PIC GOT ptr */
             "movl %6,%%ebx;" /* move new_val2 to %ebx */
             "lock; cmpxchg8b %0; setz %1;"
             "pop %%ebx;"     /* restore %ebx */
                 : "=m"(*mem), "=q"(result)
             : "m"(*mem), "d" (old.b), "a" (old.a),
               "c" (new.b), "m" (new.a) : "memory");

Unfortunately, this isn't a generic solution. It works fine with the PIC case, because gcc will not allocate ebx for anything else. But in the non-PIC case, there is a chance that ebx will be used for addr. This would cause a probably fairly tricky bug to track down!

The solution is to use the #if __PIC__ directive to either tell gcc you're clobbering ebx in the non-PIC case, or just keep two versions around; one that saves and restores ebx for PIC and one that doesn't.