| description | Planet SLUG - http://planet.slug.org.au/ |
|---|---|
| language | en |
| link | http://planet.slug.org.au/ |
http://feedproxy.google.com/~r/zhasper/~3/peA1DQnhJM4/
From My New Year’s Resolution: Be A Proud Creationist:
The second message was even more bizarre. After the excitement of the first message and the realisation that there was only Australian beer left and the sun hadn’t yet set, we were rapt to see the skywriter trace out the word ‘THE’. We gazed on as he added, ‘CREATOR’. Intrigued, we cooed as the pilot scrawled ‘IS’… and waited for the payoff…
‘JESUS‘.
Fuck. I mean, that’s not even biblically accurate, surely! Jesus doesn’t come in until after the Triwizard Tournament! According to Genesis, Yahwehdidit. He was so clever, he managed to create the world twice in two different orders!
See, I lost interest in this even earlier: when I last saw this bit of drivel it had just turned into “The”, and I got bored and went back inside. For a few moments before that, the sky had proudly been advertising “THC”…
(Side note: I found this past via a pingback on Stilgherrian’s post “Telstra, you goddam bloody idiots!” - you’ll have to read both posts to figure out the connection)
http://jeremy.visser.name/2009/01/03/musings-on-copyright-dates/
In the context of a blog, with lots of posts from different years, how would copyright apply? Would each post on the blog have a separate copyright? Or would the blog have a copyright as a whole? Or is it up to the author how it should work?
Say I added a footer to the bottom of my blog in the year 2005, which reads:
Copyright © 2005 by Jeremy Visser. All rights reserved.
(Please note that the copyright notices in this post are purely for discussion and illustrative purposes, and are not intended to state the true copyrighted nature of any of the content on this website.)
Now, it’s the year 2009, so there seems to be two popular ways to update this kind of line:
So in the latter one, the copyright date is simply bumped up to 2009. Is it legal to arbitrarily bump the copyright expiration date like that without formal renewal?
In Australia, this is not a problem, as copyright expires 70 years after the author’s death — it has nothing to do with the publication date. In which case, it does not make sense to add a year to copyright declarations of Australian works. I think the following would do fine for me:
Copyright © by Jeremy Visser. All rights reserved.
It would then be up to somebody to look up the date of my death to find out if any of my works are in the public domain.
So why do we add dates to copyright notices? In the United States, the case is the same as Australia — copyright expires 70 years after the death of an author.
I could not find any information on how copyright expiration applies to a corporation in Australia (after all, a corporation cannot die), but in the United States, copyright on a work produced by somebody as part of their official duties while working for a corporation expires 95 years after publication or 120 years after creation (whichever is shorter). In this case, adding dates to copyright notices does make sense.
So, it seems to me that the reason we all add dates to our copyright notices is because we are all sheep and simply copy each others’ copyright notices. Ironic, eh?
http://puzzling.org/logs/thoughts/2009/January/3/backup-policies
Via slashdot.org (yes really, I still pull in the headlines, although the miracle of feed readers has allowed me to confirm that yes, Ars Technica is a better read), a site called Journal Space, which hosted weblogs, lost all their data. They only had a RAID setup as backup, that is, a system that mirrors content between two disks and is designed to protect against disk failure. If you've heard of RAID, you hopefully already know that it is not the same as a backup: if software error or an accident or a malicious act deletes data from one disk, the RAID setup faithfully mirrors it to the other disk. If not, imagine that you have two magical whiteboards. One is copied exactly to the other. If one magical whiteboard totally breaks down, excellent, you have a full copy of your meeting notes and doodles on the other. (Note for accuracy, not all RAID configurations produce a full mirror and sometimes the mirror is spread over more than one spare disk. But you get the idea.) However, if someone rubs something off the whiteboard, or falls over while holding a can of solvent and splashes it on the first whiteboard, everything on it is immediately deleted from the other.
Instead, for home machines you want, most likely, an incremental backup, that is, a separate disk/machine with several copies of your data going back in time. Your data as it was an hour ago. Your data as it was a day ago. Your data as it was a month ago. And so on. I have snapshots of my data for every three hours over the last two months. (Sensible backup programs will notice when data is the same across two or more time periods and only store it once, so your backup disk does not need to be so very much larger than your normal disk.)
For business systems you want both: the quick recovery from disk failure that mirroring systems such as RAID offer, and incremental backups. (I don't maintain business grade systems, ask someone else for best practices if you need them. Internally consistent database backups are something you want to pay particular attention to.)
I note this because in November I gave a talk on home backups for Linux at SLUG and there is one other point of interest: do not trust third party providers to have good backups. It is getting increasingly common to have a lot of your most interesting data on someone else's servers: your email on Google's, your blog over at wordpress.com, contact details for all your friends on Facebook, and so on. But your provider can make both their own catastrophically bad decisions, like Journal Space, and have their creditors suddenly sell their hard disks off in a fire sale, as happened to Digital Railroad.
Which is a big problem, because a lot of third party providers do not provide an easy way to get your data ('easy' would be both a documented API accessible from common programming languages and an installable application), and lots don't provide any way at all. (There's also a whole batch of interesting issues to do with your comments or Wall postings or whatever: you don't necessarily have the right to reproduce them and there would be privacy implications when allowing you to back them up and reproduce them on some other side. LiveJournal, for one, solves this problem by not allowing easy backups of comments left on your journal.)
If your email host, blog host, calendar host, documents host or social networking host failed or deleted your account, how would you fare?
http://puzzling.org/logs/thoughts/2009/January/2/ny-encouragements
From RavenBlack:
New Year's Encouragements. Instead of making pressurey resolutions for yourself, make positive uplifting recommendations for other people. No negativity allowed, and try not to even imply something negative (eg. "eat better" implies you were eating poorly, but "make delicious home-cooked meals at least once a week" is pretty cleanly positive, and "make more delicious home-cooked meals because your cooking is great" is better still.)
Anyone with encouragements of this positive type may contact me via my preferred method or my LiveJournal, if you have access. (I am beginning, finally, to think about allowing comments on puzzling.org directly, but it's not likely to happen very soon.)
You are hereby invited to do this in your own weblog.
http://benno.id.au/blog/2009/01/02/using-gdb-with-skyeye
This post is basically a crash course in using gdb to run and debug
low-level code. Learning to us a debugger effectively can
be much more powerful than ghetto printf() and putc()
debugging. I should point out that I am far from a power-gdb user, and
am usually much more comfortable with printf() and putc(),
so this is very much a beginners guide, written by a newbie. With those
caveats in mind, lets get started.
So the first thing to do is to get our target up and running. For
this our target will be a virtual device running with Skyeye. When you start up
Skyeye and pass it the -d flag, e.g: $ skeye -c
config.cfg -d. This will halt the virtual processor and provide
an opportunity to attach the debugger. The debugger will be available
on a UNIX socket. It defaults to port 12345. Of course
a decent JTAG adapter should be able to give you the same type of
thing with real hardware.
Now, you run GDB: $ arm-elf-gdb. Once gdb is running
you need to attach to the target. To do this we use:
(gdb) target remote :12345. Now you can start the
code running with (gdb) continue.
Now, just running the code isn’t very useful, you can do that already.
If you are debugging you probably want to step through the code.
You do this with the step command. You can step through
code line at-a-time, or instruction at-a-time. At the earliest stages
you probably want to use the si command to step through
instruction at-a-time.
To see what you code is doing you probably want to be able to display
information. For low-level start up code, being able to inspect the register
and memory state is import. You can look at the register using the
info registers command, which prints out all the general-purpose
registers as well as the program counter and status registers.
For examing memory the x command is invaluable. The
examine command takes a memory address as an argument (actually, it
can be a general expression that quates to a memory address). The
command has some optional arguments. You can choose the number of
units to display, the format to display memory in (hex (x), decimal
(d), binary (t), character (c), instruction (i), string(s), etc), and
also the unit size (byte (b), halfword (h), word (w)). So, for
example to display the first five words in memory as hex we can do:
(gdb) x /5x 0x0. If we want to see the values of
individual bytes as decimal we could do: (gdb) x /20bd 0x0.
Another common example is to display the next 5 instructions, which can
be done with (gdb) x /5i $pc. The $pc expression
returns the value in the pc register.
Poking at bits and bytes and stepping instruction at a time is
great for low-level code, but gdb can end up being a lot more useful
if it knows a little bit more about the source code you are
debugging. If you have compiled the source code with the
-g option, your ELF file should have the debugging
information you need embedded in it. You can let gdb know about this
file by using the (gdb) symbol program.elf. Now
that you actually have symbols and debugging information, you can
do things like normal then step command, and it will
step through lines of source code (rather than instructions).
The other nice thing you have is that you can easily set
breakpoint and watchpoints. (You don’t have to have
source debugging enabled for this, but it makes things a lot easier!).
Seting a breakpoint is easy, you can set it on a line e.g: (gdb) break file.c:37,
or on a particular function e.g: (gdb) break schedule.
Breakpoints are neat, but watchpoints are even cooler, since you can
test for a specific conditions e.g: (gdb) watch mask 2000.
Now that you have these nice watchpoints and breakpoints, you
probably find that most of the time, you just end up printing out some
variables each time you hit the point. To avoid this repetitive typing
you can use the display command. Each expression you
install with the display command will be printed each time program execution
stops (e.g: you hit a break-point or watch-point). This avoids a lot
of tedious typing!
So, this is of course just scratching the surface. One final thing
to consider that will likely make your time using gdb more useful and
less painful (i.e: less repetitive typing), is the define
command which lets you create simple little command scripts. The other
is that when you start gdb you can pass a command script with the
-x. So, you might want to consider, instead of littering
your code with printf() statements everywhere you might want to write
some gdb commands that enable a breakpoint and display some the relevant
data.
Good luck, and happy debugging!
http://benno.id.au/blog/2009/01/02/literal-pools
Yesterday we saw how with some careful programming, and the right compiler flags we could get GCC to generate optimally small code for our particular function. In this post we take a look at one of the ways in which GCC fails to produce optimal code. Now there are actually many ways, but the I want to concentrate on in this post is the use of literal pools.
So, what is a literal pool? I’m glad you asked. The
literal pool is an area of memory (in the text segment), which is used
to store constants. These constants could be plain numerical
constants, but their main use is to store the address of variables
in the system. These addresses are needed because the ARM instruction
does not have any instructions for directly loading (or storing) an
address in memory. Instead ldr and str can only
store at a ±12-bit offset from a register. Now there are lots of ways
you could generate code with this restriction, for example, you could ensure
your data section is less than 8KiB in size, and reserve a register
to be used as a base for all data lookups. But such approach only works
if you have a limited data section size. The standard approach that is
taken is that when a variable is used its address is written out
into a literal pool. The compiler then generates two instructions, first
to read the address from this literal pool, and the second is the
instruction to access the variable.
So, how exactly does this literal pool work? Well, so that a
special register is not needed to point at the literal pool, the
compiler uses the program counter (PC) register as the
base register. The generated codes looks something like: ldr r3,
[pc, #28]. That codes loads a value at a 28-byte offset from
the current value of PC into the register
r3. r3 then contains the address of the
variable we want to access, and can be used like: ldr r1, [r3,
#0], which loads the value of the variable (rather than the
address) into r1. Now, as the PC is used as
the base for the literal pool access, it should be clear that the
literal pool is stored close enough to the code that needs to use it.
To ensure that the literal pool is close enough to the code using it, the compiler stores a literal pool at the end of each function. This approach works pretty well (unless you have a 4KiB+ function, which would be silly anyway), but can be a bit of a waste.
To illustrate the problem, consider this (contrived) example code:
static unsigned int value;
unsigned int
get_value(void)
{
return value;
}
void
set_value(unsigned int x)
{
value = x;
}
Now, while this example is contrived, the pattern involved exhibits
itself in a lot of real-world code. You have some private data in a
compilation unit (value), and then you have a set of
accessor (get_value) and mutator (set_value)
functions that operate on the private data. Usually the functions would
be more complex than in our example, and usually there would be more
than two. So lets have a look at the generated code:
00000000 <get_value>: get_value(): 0: 4b01 ldr r3, [pc, #4] (8 <get_value+0x8>) 2: 6818 ldr r0, [r3, #0] 4: 4770 bx lr 6: 46c0 nop (mov r8, r8) 8: 00000000 .word 0x00000000 8: R_ARM_ABS32 .bss 0000000c <set_value>: set_value(): c: 4b01 ldr r3, [pc, #4] (14 <set_value+0x8>) e: 6018 str r0, [r3, #0] 10: 4770 bx lr 12: 46c0 nop (mov r8, r8) 14: 00000000 .word 0x00000000 14: R_ARM_ABS32 .bss
You can see that each function has a literal pool (at address 0x8
and 0x14). You can also see that there is a relocation associated with
each of these addresses (R_ARM_ABS32 .bss). This
relocation means that at link time the address of value
will be stored at locations 0x8 and 0x14. So, what is the big deal
here? Well, there are two problems. First, we have two literal pools
containing duplicate data, by storing the address of
value twice, we are wasting 4 bytes (remember from
yesterday, we have a very tight memory budget and we care where every
byte goes). The second problem, is that we need to insert a nop
in the code (at address 0x6 and 0x12), because the literal pool must
be aligned.
So, how could the compiler be smarter? Well, if instead of generating a literal pool for each individual function it did it for the whole compilation unit, then instead of having lots of little literal pools with duplicated data through-out, we would have a single literal pool for the whole file. As a bonus, you would only need alignment once as well! Obviously if the compilation unit ends up being larger than 4KiB then you have a problem, but in this case you could still save up producing the literal pool until after 4KiB worth of code. As it turns out the commercial compiler from ARM, RVCT, does exactly this. So lets have a look at the code it generates:
00000000 <get_value>: get_value(): 0: 4802 ldr r0, [pc, #8] (c <set_value+0x6>) 2: 6800 ldr r0, [r0, #0] 4: 4770 bx lr 00000006 <set_value>: set_value(): 6: 4901 ldr r1, [pc, #4] (c <set_value+0x6>) 8: 6008 str r0, [r1, #0] a: 4770 bx lr c: 00000000 .word 0x00000000 c: R_ARM_ABS32 .data$0
You see that the code is more or less the same, but there is just
one literal pool right at the end of the file, and no extra
nops are needed for alignment. Without merging literal
pools we have a .text size of 24 bytes, with the merging we slash
that down to 16 bytes.
So merging literal pools is pretty good, but the frustrating thing is that in this example, we don’t even need the literal pool!. If we examine the final compiled image for this program:
Disassembly of section ER_RO:
00008000 <get_value>:
get_value():
8000: 4802 ldr r0, [pc, #8] (800c <set_value+0x6>)
8002: 6800 ldr r0, [r0, #0]
8004: 4770 bx lr
00008006 <set_value>:
set_value():
8006: 4901 ldr r1, [pc, #4] (800c <set_value+0x6>)
8008: 6008 str r0, [r1, #0]
800a: 4770 bx lr
800c: 00008010 .word 0x00008010
Disassembly of section ER_RW:
00008010 <value>:
8010: 00000000 .word 0x00000000
You should notice that the actual location of the value variable is
0x8010. At address 0x800c we have the literal pool storing
the address of a variable which is in the very next word! If we optimised this
by hand, we would end up with something like (need to verify the offset):
Disassembly of section ER_RO:
00008000 <get_value>:
get_value():
8000: 4802 ldr r0, [pc, #4] (8008 <set_value+0x8>)
8002: 4770 bx lr
00008004 <set_value>:
set_value():
8004: 6008 str r0, [pc, #0]
8006: 4770 bx lr
Disassembly of section ER_RW:
00008008 <value>:
8008: 00000000 .word 0x00000000
If we get rid of the literal pool entirely, we save the memory of the literal pool itself (4 bytes), plus the two instructions need to load values out of the literal pool (4 bytes). This cuts our text size down to a total of only 8 bytes! This is a factor 3 improvement over the GCC generated code. Granted, you are not always going to be able to perform this type of optimisation, but when you care about size, it is quite important. It would be nice if gcc supported a small data section concept so that you could specify variables that essentially resised within the literal pool instead of needing an expensive (in terms of space and time) indirection.
For this project, it looks like the code will have to be hand tweaked assembler, which is frustrating, because when you use a person as your compiler iterations become really expensive, and you want to make sure you get your design right up front.
http://airlied.livejournal.com/64942.html
Isabel was delivered this morning, at 11:54am, at 8lb13oz (4.07kg).
I'll be slow on anything non-baby related for a while :)
http://feedproxy.google.com/~r/zhasper/~3/J_FcqPhNDYk/
People have been telling me to read STR for ages, but I’ve never got around to it. Pascal just went to the site while I was shoulder surfing - and thus I discovered this review of Ubuntu:
One of the great things about Windows is the ease of obtaining powerful utilities and applications. In addition to hundreds of great titles available on CD-ROM you can download awesome shareware applications: simply click on Setup.exe and most installers will instantly deploy your chosen software, sometimes with cool bonus productivity apps that enhance your browsing experience. In comparison with Microsoft’s common-sense approach, pandemonium reigns on the Linux platform.
The only way to install software is via a tool called the ‘package manager’ which is confusingly also called ‘Synaptic’. This works according to a similar principle as a communist super-market: You have a limited range of software which has been chosen on a purely ideological basis rather than functionality. If you want to ‘think different’, it’s tough-luck again: Another obvious fail for the ‘contender’.
To make matters worse, in order to install an application you must be ‘root’ which entails memorizing a series of confusing passwords. By contrast Windows allows any user to install the applications they need to do their work - a wise productivity gain that endears the flexible NT platform to IT departments the world over.
The rest is good reading too. Very informative! I’m switching away from Ubuntu forthwith.
http://marty.sunriseroad.net/2009/01/01/a-short-holiday-read-and-an-insight-into-me/
Around 1993 was probably a big turning point in my career life. Up until then I had spent a lot of time involved in designing and implementing solutions around process control systems at the Port Kembla Steelworks. When I graduated (in 1985) I was doing straight electrical control work as well as some PLC (programmable logic control systems work). A few years later I was writing FORTRAN code than allowed operators to control big machines (such as plate mills and cranes). I became fascinated with communications and networking, and started doing work in that front in the late 80’s, a lot of this was around the low-level communications between process control computers, but also more general networking like DECnet. I got introduced into UNIX and C in the early 90’s, both doing some communications driver coding as well as X11 based operator interfaces. I bought my first PC for home in 1993 and made sure it could run Windows 3.1 and Linux (SLS, which later begat Slackware, on around 30 floppies was my first distro). I had BBS access and the ‘net soon enough as well. I guess, just like today, I was always reading about new things, and at least having a bit of a play at making things work.
One thing I had a little play with at the time was VRML, which is a 3D markup language. At work we also started using the Internet tools a lot. Also the new engineering projects were all being done in CAD, some in 3D, with intent on being better able to plan all the services required on such huge mechanical and civil works. I was also a big fan of raytracing, particularly POVray. Anyway, I saw all this coming together, potentially a huge aid to engineering support. I was starting to becoming more focussed on IP, ATM and other network protocols so it probably was almost farewell to process control world.
So I wrote the following short-story in 1993. The chief electrical engineer at the time loved it, and it appeared in the departmental newsletter. I think it was quite well received, though it is probably the first and only short story I have had published. I have made a few small edits from the original, mainly to make it a little clearer to non-steelworkers. I hope you like it!
The VirtEng.
Kurt abruptly woke from his doze as the ‘comm indicated that his attention was required. Despite wanting to throw a heavy object at it, he heeded the ringing.
” ‘Comm answer...Greber here, who is it?”
“It’s Max, with got a problem at the Finishing Mill again; hyper-axial gamma ray gauge it seems.”. The last thing Kurt wanted to see on the ‘comm screen was Max.
“Strike, can’t I get a moment’s peace, even out here?” He gazed solemnly at the gently swaying palm trees, and the glistening sand out of his window. “OK I’ll get on to it. Bye. ‘Comm hangup.”
Reluctantly, Kurt stepped across his room and donned the VirtEng, and waited for the retinal scan to authorise him.
“VirtEng …Goto Port Kembla Finishing Mill” he uttered to the machine. In an instant he felt the familiar experience of floating above this bane of his life. As he pointed his way down, the VirtEng displayed the detail of the 21 stand rolling mill. The physical view of the mill from above always fascinated him despite rather being someplace else. The hundreds of tonnes of metal and motors and hydraulics had to be coordinated to within a micron in microseconds in order to make the steel strip of the correct properties. As he came up level with the end of the mill, his attention was drawn to the pinkish hue of the gamma ray thickness gauge. For years now the VirtEngs had been able to diagnose equipment status, even subtle problems, and give an indicative colour to the components. “Just out of tolerance” he thought as he mused on the problem.
“VirtEng … Logical view” he instructed his helmet and the scene before him faded and a conglomeration of blocks and lines appeared. He began walking past the various schematic components of the gauge. Occasionally he would stop at an amplifier or processor and point at the various panels before him. Charts showing the equipment status immediately appeared before him as he pursued a prognosis of the fault. He could also access a history of this component; not just in this gauge, but of course the database was continually fed by input from all the installations in the world. “It must be this proton accumulator” he thought, “I’ll get the Auto-Tric”. After issuing the dispatch, he investigated the software problem that caused the overload. Again each instruction could be removed, visually displaying a history of past values and execution sequences. After tuning a parameter down with a downward wipe of his finger and satisfied with his work, Kurt thought he’d call it a day.
Just after he issued the “VirtEng …Physical view” command he made out the shape of the “Auto-tric” trundling down the mill floor. With a PA-481F in the manipulator, the ‘droid electrician approached the gauge and within a minute had the component replaced and tested. Without as much as a nod the robot returned to the Parts Dispatch Terminal from whence it came. As the mill commenced rolling again, Kurt felt comfortable with the soft blue emanating from the gamma gauge, indicating it’s sound health.
Just as Kurt turned to depart, his virtual image bumped into the virtual image of the Mill Superintendent.
“Thanks for that Kurt, I thought you were on R&R, but I knew you would help us out”.
“Sure, It’s only Fiji, I’ve been there before anyhow.” As the stereo headset filled with sound of metal meeting metal, Kurt issued his “Log out” to the machine and returned to the pleasant scenery and sounds at his window of a few minutes before the call-out. He returned to his couch for another snooze, in readiness for a late afternoon surf. As sleep drifted back, a thought entered his head - “I wonder what people did before VirtHoliday?”Martin Visser – copyright 1993 - 2009
http://benno.id.au/blog/2009/01/01/space_conserving_code
A project that I’m working on at the moment calls for a very small footprint. This post is about how to make code really small for the ARM architecture.
As you can probably guess, I’m interested in operating system code, so as an example, I’ve taken a very simple piece of operating system code, and stripped it right back to demonstrate some of the techniques to use when optimising for space. So here is the snippet of code we are going to optimise:
01 struct thread {
02 unsigned int notify_bits;
03 };
04
05 unsigned int
06 poll(struct thread *thread, unsigned int mask)
07 {
08 unsigned int result;
09 result = thread->notify_bits & mask;
10 if (result) {
11 thread->notify_bits &= ~result;
12 }
13 return result;
14 }
In this very simple operating system we have threads (thread data
is stored in struct thread). Each thread has a set of 32
signals (encoded in a single word notify_bits). This poll
is used by a thread to determine if it has been sent any signals. The
mask parameter is the set of signals that the thread is
interested in checking. So, a thread can check if a single signal has
been thread, or if any signal has been set, or if a specific subset of
signals has been set. The function returns the signals that are
available (which is simply the bit-wise and of
notify_bits and mask). It is important that
the function clears any signals that have been returned. This makes
sure that if poll is called twice the same signals are
not returned. This is achieved in lines 10—12.
So, our goal is to try and get this code as small as possible.
And every byte counts! First off, we just try and compile
this with the standard ARM gcc compiler. I’m using version 4.2.2.
So we start with: $ arm-elf-gcc -c poll.c -o poll.o.
We can then use object dump to work out what the compiler did:
$ arm-elf-objdump -dl poll.o.
00000000 <poll&ht:
poll():
0: e1a0c00d mov ip, sp
4: e92dd800 push {fp, ip, lr, pc}
8: e24cb004 sub fp, ip, #4 ; 0x4
c: e24dd00c sub sp, sp, #12 ; 0xc
10: e50b0014 str r0, [fp, #-20]
14: e50b1018 str r1, [fp, #-24]
18: e51b3014 ldr r3, [fp, #-20]
1c: e5932000 ldr r2, [r3]
20: e51b3018 ldr r3, [fp, #-24]
24: e0023003 and r3, r2, r3
28: e50b3010 str r3, [fp, #-16]
2c: e51b3010 ldr r3, [fp, #-16]
30: e3530000 cmp r3, #0 ; 0x0
34: 0a000006 beq 54 <poll+0x54>
38: e51b3014 ldr r3, [fp, #-20]
3c: e5932000 ldr r2, [r3]
40: e51b3010 ldr r3, [fp, #-16]
44: e1e03003 mvn r3, r3
48: e0022003 and r2, r2, r3
4c: e51b3014 ldr r3, [fp, #-20]
50: e5832000 str r2, [r3]
54: e51b3010 ldr r3, [fp, #-16]
58: e1a00003 mov r0, r3
5c: e24bd00c sub sp, fp, #12 ; 0xc
60: e89da800 ldm sp, {fp, sp, pc}
So, our first go gets us 100 bytes of code. Which is 10 bytes
(or 2.5 instructions) for each of our lines of code. We should be able
to do better. Well, the first thing is we should try is to use
optimisation: $ arm-elf-gcc -c poll.c -o poll.o -O2. This
gives us a much better code generation output:
00000000 <poll>: poll(): 0: e5902000 ldr r2, [r0] 4: e1a0c000 mov ip, r0 8: e0110002 ands r0, r1, r2 c: 11e03000 mvnne r3, r0 10: 10033002 andne r3, r3, r2 14: 158c3000 strne r3, [ip] 18: e12fff1e bx lr
So this got us down to 28 bytes. A factor 4 improvement for one
compiler flag, not bad. Now, -O2 does some standard
omptimisations, but -Os, will do optimisations
specifically for reducing the amount of code. So trying:
$ arm-elf-gcc -c poll.c -o poll.o -Os. This gives
a little bit better code-gen:
00000000 <poll>: poll(): 0: e5903000 ldr r3, [r0] 4: e1a02000 mov r2, r0 8: e0110003 ands r0, r1, r3 c: 11c33000 bicne r3, r3, r0 10: 15823000 strne r3, [r2] 14: e12fff1e bx lr
Down to 24 bytes (6 instructions), is pretty good. Now, as you can
see the generated code has 32-bits per instruction. The some of the
ARM architectures have two distinct instruction sets,
ARM and Thumb. The Thumb instruction
set uses 16-bit per instruction, instead of 32-bit. This denser
instruction set can enable much smaller code sizes. Of course there is
a trade-off here. The functionality of the 16-bit instructions is
going to be less than the 32-bit instructions. But lets give it a
try. At the same time, we will tell the compiler the exact CPU we want
to compile for (which is the ARM7TDMI-S) in our case. The compiler
line is: $ arm-elf-gcc -c poll.c -o poll.o -Os -mcpu=arm7tdmi
-mthumb.
Which produces code like:
00000000 <poll>: poll(): 0: 6803 ldr r3, [r0, #0] 2: 1c02 adds r2, r0, #0 4: 1c08 adds r0, r1, #0 6: 4018 ands r0, r3 8: d001 beq.n e <poll+0xe> a: 4383 bics r3, r0 c: 6013 str r3, [r2, #0] e: 4770 bx lr
So, now we are down to 16 bytes, so in Thumb we need 8 instructions (2 more than ARM), but each is only 2 bytes, not 4, so we end up with a 1/3 improvement. To get any further, we need to start looking at our code again, and see if there are ways of improving the code. Looking at the code again:
00 unsigned int
01 poll(struct thread *thread, unsigned int mask)
02 {
03 unsigned int result;
04 result = thread->notify_bits & mask;
05 if (result) {
06 thread->notify_bits &= ~result;
07 }
08 return result;
09 }
You may notice that the branch instruction on line 5, you may
notice that this is actually redundant. If result is
zero, then ~result well be 0xffffffff. Given
this thread->notify_bits &= 0xffffffff will not change
the value of thread->notify_bits. So, we can reduce this
to:
00 unsigned int
01 poll(struct thread *thread, unsigned int mask)
02 {
03 unsigned int result;
04 result = thread->notify_bits & mask;
05 thread->notify_bits &= ~result;
06 return result;
07 }
When we compile this we get down to:
00000000 <poll>: poll(): 0: 6803 ldr r3, [r0, #0] 2: 4019 ands r1, r3 4: 438b bics r3, r1 6: 6003 str r3, [r0, #0] 8: 1c08 adds r0, r1, #0 a: 4770 bx lr
This gets us down to 6 instructions (12 bytes). Pretty good since
we started at 100 bytes. Now lets look at the object code in a little
bit more detail. If you look at address 0x8, the instruction simply
moves register r1 into register r0 so that
it in the right place for return. (Note: The ARM ABI has the
return value stored in r0). This seems like a bit of a waste, it
would be good if there was a way we could have the value stored
in r0 and not waste an instruction just moving values
between registers. Now, to get a better understanding of what the
instructions are doing, I’m going to slightly rewrite the code, and
then compile with debugging, so we can see how the generated code
matches up with the source code. So first, lets rewrite the code a little
bit:
00 unsigned int
01 poll(struct thread *thread, unsigned int mask)
02 {
03 unsigned int tmp_notify_bits = thread->notify_bits;
04 mask &= tmp_notify_bits;
05 tmp_notify_bits &= ~mask;
06 thread->notify_bits = tmp_notify_bits;
07 return mask;
08 }
You should convince yourself that this code is equivalent to the
existing code. (The code generated is identical). So, we can now line
up the source code with the generated code. On line 03 (unsigned
int tmp_notify_bits = thread->notify_bits), this matches up
with address 0x0 (ldr r3, [r0, #0]). So, register
r3 is used to store variable
tmp_notify_bits. The parameter thread is stored in
register r0. Now, line 04 (mask &=
tmp_notify_bits) matches directly with address 0x2 (ands
r1, r3). Register r1 matches directly with the
mask parameter. The important part of restructuring the
code as we have done, is that it becomes obvious that we can directly
using the mask parameter instead of needing an extra variable like in
the previous code. As we continue line 05 (tmp_notify_bits &=
~mask), matches directly to 0x4 (bics r3, r1). The bics
instruction is quite neat in that it can essentially do the &=
~ in one 16-bit instruction. Line 06
(thread->notify_bits = tmp_notify_bits) stores the
result back to memory, matches directly to 0x6. Now the final line of
code (return mask;), needs two instructions 0x8 and 0xa
(adds r0, r1, #0 and bx lr). Now the reason we need to instructions
is because mask is stored in register r1, and the return
value needs to be in register r0. So how can we get mask
to be stored in r0 all along? Well, if we switch the
parameters around poll(unsigned int mask, struct thread
*thread), the mask will instead be stored in
r0 instead of r1. (Note: We don’t
necessarily have to change the interface of the function. If we want
to support keep the interface we can use a simple macro to textually
swap the parameters.) If we compile this, we get the following
generated code:
00000000 <poll>: poll(): 0: 680b ldr r3, [r1, #0] 2: 4018 ands r0, r3 4: 4383 bics r3, r0 6: 600b str r3, [r1, #0] 8: 4770 bx lr
So, we have got this down to 5 instructions, 10 bytes. This is a factor 10 improvement, not bad!
So a bit of a review:
-Os to optimise for space.http://feedproxy.google.com/~r/zhasper/~3/_2m0Wp29kTo/
Firemen here to put out the oven fire http://skitch.com/jdumay/97em/kitchenonfire.
http://puzzling.org/logs/thoughts/2009/January/1/2009-plans
One year I'd like to do the same project Skud is doing for 2009, that is: a resolution a week. But this year is a finishing year for me, not a starting year.
A quick wrap-up on 2008 resolutions:
The first half of 2008 was pretty difficult for me. In retaliation, Andrew and I screamed around the south island of New Zealand in August. I do recommend its recuperative powers.
Major goals for 2009:
Other plans in 2009:
Also, given the PhD submission thing, I will probably be looking for a job towards the end of 2009. I do not know yet if I am going to apply for postdoctoral positions, this will probably depend on achieving a couple of major conference acceptances in 2009. And on deciding whether I want to live in the northern hemisphere. Even if I am I may be looking for programming or similar work in the short-term to wait out my examination process. So, keep in touch, if you want to offer me work, or come to my submission party. Or both.
http://blog.heimic.net/2008/12/31/back-from-little-break/
Just got back today from Port Macquarie. It was a 5 hour drive back, which was alright. I figured if we left tomorrow or even in the next few days then the delays would be bad, so we only planned to stay until the 31st and then make an early break.
Traffic was good, as compared to the day we went up. However managed to see 3 radar traps and come by one mobile RBT. Cops were out writing tickets, no doubt about that.
http://jeremy.visser.name/2008/12/31/some-logos/
Okay, what do these logos have in common?
They all use stripes, and they’re ugly. Ugly, I tell you. I don’t know why, but I hate logos that use stripes like these. Please, just use gradients, drop shadows, or just go psycho with the gloss.
http://www.mega-nerd.com/erikd/Blog/CodeHacking/Haskell/parsec_expression_parsing.html
Haskell's Parsec parsing library (distributed with the GHC compiler since at least version 6.8.2) contains a very powerful expression parsing module Text.ParserCombinators.Parsec.Expr. This module makes it easy to correctly parse arithmetic expressions like the following according to the usual programming language precedence rules.
2 + a * 4 - b
Once parsed, the abstract syntax tree for that expression should look like this:
The original Parsec paper by Daan Leijen even gives a small example of using the expression parser. As can be seen below, the operators are defined in a table (ie a list of lists) where the outer list is a set precedence levels (from highest precedence to lowest) and each inner list specifies all the operators for that precedence level.
module Parser
where
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Expr
expr :: Parser Integer
expr = buildExpressionParser table factor <?> "expression"
table :: [[ Operator Char st Integer ]]
table = [
[ op "*" (*) AssocLeft, op "/" div AssocLeft ],
[ op "+" (+) AssocLeft, op "-" (-) AssocLeft ]
]
where
op s f assoc = Infix (do { string s ; return f }) assoc
factor = do { char '(' ; x - expr ; char ')' ; return x }
<|> number
<?> "simple expression"
number :: Parser Integer
number = do { ds <- many1 digit; return (read ds) } <?> "number"
The above simple example works fine but there is a potential for a rather subtle problem if the expression parser is used in conjunction with the Text.ParserCombinators.Parsec.Token module.
The problem arises when trying to parse expressions in C-like languages which have bitwise OR (|) as well as logical OR (||) and where the bitwise operation has higher precedence than the logical. The symptom was that code containing the logical OR would fail because the expression parser was finding two bitwise ORs. After banging my head against this problem for a considerable time, I posted a problem description with a request for clues to the Haskell Cafe mailing list with the following code snippet:
import qualified Text.ParserCombinators.Parsec.Expr as E
opTable :: [[ E.Operator Char st Expression ]]
opTable = [
-- Operators listed from highest precedence to lowest precedence.
{- snip, snip -}
[ binaryOp "&" BinOpBinAnd E.AssocLeft ],
[ binaryOp "^" BinOpBinXor E.AssocLeft ],
[ binaryOp "|" BinOpBinOr E.AssocLeft ],
[ binaryOp "&&" BinOpLogAnd E.AssocLeft ],
[ binaryOp "||" BinOpLogOr E.AssocLeft ]
]
binaryOp :: String -> (SourcePos -> a -> a -> a)
-> E.Assoc -> E.Operator Char st a
binaryOp name con assoc =
E.Infix (reservedOp name >>
getPosition >>=
return . con) assoc
Unfortunately, no real answer was forthcoming and while I still held out hope that an answer might eventuate, I continued to work on the problem.
Eventually, after reasoning about the problem and looking at the source code to the Token module I realised that the problem was with the behaviour of the reservedOp combinator. This combinator was simply matching the given string at the first precedence level it found so that even if the code contained a logical OR (||) the higher precedence bitwise OR would match leaving the second vertical bar character un-parsed.
My first attempt at a solution to this problem was to define my own combinator reservedOpNf using Parsec's notFollowedBy combinator and use that in place of the problematic reservedOp.
opChar :: String opChar = "+-/%*=!<>|&^~" reservedOpNf :: String -> CharParser st () reservedOpNf name = try (reservedOp name >> notFollowedBy (oneOf opChar))
This solved the immediate problem of distinguishing between bitwise and logical OR, but I soon ran into another problem parsing expressions like this:
if (whatever == -1)
.....
which were failing at the unary minus.
A bit of experimenting suggested that again, the problem was with the behaviour of the reservedOp combinator. In this case it seemed the combinator was matching the given string, consuming any trailing whitespace and then the notFollowedBy was failing on the unary minus.
Once the problem was understood, the solution was easy, replace the reservedOp combinator with the string combinator (which matches the string exactly and doesn't consume trailing whitespace), followed by the notFollowedBy and then finally use the whiteSpace combinator to chew up trailing white space.
reservedOpNf :: String -> CharParser st ()
reservedOpNf name =
try (string name >> notFollowedBy (oneOf opChar) >> whiteSpace)
Despite minor problems like the one above, I am still incredibly impressed with the ease of use and power of Parsec. Over the years I have written numerous parsers, in multiple host languages, using a number of parser generators and I have never before used anything that comes close to matching Haskell and Parsec.
http://openskills.blogspot.com/2008/12/new-version-of-hyper.html
Hyper is a Smalltalk library available under the LGPL which implements RFC 2616 and friends aka HTTP. You can use Hyper to build a web server or a web client. As an example, you could use Hyper as an HTTP server underneath Seaside (a rather cool website content library).
The new version is 1 340 and can be found in the Cincom public Store repository. This version picks up a number of changes made by Dale Henrichs of GemStone. Thanks Dale!
There are no big changes here, but if you happen to want to run a robust HTTP server for Seaside from within your Gemstone database, then this is the version for you.
Have fun :-)
http://airlied.livejournal.com/64691.html
AMD today pushed the initial code to support acceleration on the r600/r700 range of GPUs.
This consists of r6xx-r7xx-support branches in the drm, radeonhd and a new r600_demo repo.
This code is really only for developers at this point but its great to see AMD finally get things lined up to allow this code to be released.
I've only been barely involved in the r600 code so far, I wrote the original drm over a few days and handed it over to AMD to continue on with, as I wanted to concentrate on the kms work. Hopefully I can get some time to look at it over the next while (yeah right, new baby still not here).
http://jamespurser.com.au/blog/LCA_09_Conflicts
Sigh looks like this LCA is going to be just like the last one I went to, full of scheduling conflicts :)
On the first day of Miniconfs we have the Business Stream, a MythTV stream and a DB stream.
On the second day of Miniconfs we have the second day of the DB stream, the Sys Admin stream, Multimedia and Virtualisation.
That's not even counting the main conference itself which has things like PHP Architecture, Scalability, and Security, Using Asterisk for Fun and Profit and Introduction to Django all in the same session times!
Sigh.
http://www.mega-nerd.com/erikd/Blog/NewHouse/hackfest_1.html
Just before Newtonmas (also known as xmas to some) I had a small hackfest in the new house that my wife and I are calling "The House that Hack Bought". We had horms, AfC, Scott, raster, kfish, pmiller and myself hacking and chatting from about 10am.
There were 5 of us in the living room:
while kfish and pmiller hacked in the sun room:
and Scott even managed to get a bit of hardware hacking done in the kitchen:
It was a great day. Thanks to all who participated.
http://airlied.livejournal.com/64271.html
So I sent a drm pull request that includes the kernel modesetting core + intel i915 driver supporting it.
This is a major milestone for a project I started working on in a previous job, and I barely remember burning through the initial code for the initial prototype in a week of little sleep.
To enable the code you need to set the CONFIG_DRM_I915_KMS, this isn't enabled by default, as we don't have a userspace that supports it available yet for general consumption. If you enable kms now, you will more than likely get a broken X for your trouble as the kernel drivers aren't compatible with having userspace drivers trample the hardware.
So where is ATI at?
although we are shipping radeon code in F10, the code is based on the TTM memory manager, which isn't really in an upstreamable
state in its current form. Hopefully a newer TTM codebase might become available that can be used upstream. If that doesn't happen, we might rearchitect the core memory manager code of the radeon system now that we have the API mostly proven. So I'm not sure when we will upstream it, it all depends on how much time I can work on it.
Baby status: due today, no sign yet, will severely impact amount of time I spend on this stuff :)
http://certifiedwaif.livejournal.com/335946.html
Having used Paige's nice sharp Global knife, I knew going back to my not so sharp knife was going to be unbearable. I always want to be able to get the best out of what I have.
I've got a Japanese cook's knife, and a French style paring knife. You might ask why I chose such an odd combination. Of course, there's a simple explanation - I had no idea what I was doing when I bought those, I just wanted something better than what I was using.
My Mum bought me a diamond steel last year for Christmas, which I've been using to sharpen and hone both my knives. Anyone who knows anything about knives is by now recoiling in horror, because they'll know that Japanese and French knives are quite different, and you shouldn't be using French sharpening technique on a Japanese knife. French knives have much thicker blades, and are usually sharpened on an angle of 20 to 30 degrees. A stone is best, but a few quick swipes with a diamond steel will keep your French knife in good condition for months at a time until it needs sharpening on a stone or machine again.
Japanese knives, with their much thinner blades, need to be sharpened differently - the industrial diamond on a diamond steel is too coarse. They're meant to be sharpened so that the edge has an angle of 10 to 15 degrees. Everything I've read, and been told by people in knife shops, says that you should use a stone. I resisted buying a stone for a long long time, because I'm a miser and hate spending money when I think I've got something that should already do the job. My brother, who's been sharpening his knives on a stone for a long time, also told me that the technique is difficult to learn.
After I gave up on the steel and bought yet another tool for sharpening, I'd have to say the result was worth it, and the while I certainly haven't mastered the technique, it's not that hard to get started. There's a pretty good explanation here that I was able to follow without too much trouble.
You might wonder why the French and Japanese knives are so different. French cuisine is very different from Japanese, with the former having emphasis on complicated technique, while the latter seems to emphasise careful preparation and presentation of ingredients, often raw e.g. sushi. So one possible explanation is that the Japanese knives are designed for the more precise and intricate cutting required by that cuisine, while the French just want to cleave through the vegetables so they can get on with making the demi-glace.
Disclaimer: I am not a chef. I haven't mastered any cuisine. This is pure speculation. Get off my lawn.
http://certifiedwaif.livejournal.com/335851.html
I went to Allans Music today hoping to get a cheap jazz guitar, or at least a cheaper jazz guitar. No such luck, even though some of the guitars were substantially reduced, they were still way out of my price range. Guitars are getting really expensive, although good guitars always have been. I think unless I'm willing to put down some serious cash, I'm going to be rocking the Strat for a few years yet. One of these days, I might just throw caution and good financial sense to the wind and buy the instrument I really want.
While I couldn't afford a new guitar on a student budget, I could afford to get a book. After having a look around, I found a nice book called the Chord Factory, from Berklee Press. Guitar players in jazz groups spend most of their time accompanying soloists, and the chords can get pretty advanced. Most of the chord books I've seen give you page after page of chord forms in every possible key, and then the implication is that you should memorise them, or maybe look them up as needed. I've never found this approach very useful - I'd much prefer to understand how the chords are built and how I can build voicings to suit my needs in a particular musical situation. I'd also really like to know how these chords are meant to be used. The closest I'd ever seen to what I was looking for was Chord Chemistry by Ted Greene, but that wasn't quite what I wanted either.
I worked out how to build voicings for major and minor chords with root notes on any string, got most of the way with dominant, minor and major seventh chords, and have no idea what to do with ninths and further extensions. I don't know how to voice those chords on guitar either, and didn't have much idea how to started. As the name suggests, the Chord Factory book is all about learning approaches to building chord voicings, rather than learning a couple of chord voicings by rote and hoping they're always going to be enough, no matter what your sadistic band leader puts on your music stand and expects you to play.
Just as important is that the book also begins to explain how to use these chords in a progression, which I've never been able to get any understanding of before. Finally ...
http://certifiedwaif.livejournal.com/335612.html
One of my house mates got a Global cook's knife yesterday. She wasn't used to such high quality (read: sharp) knives, and cut herself in the first couple of minutes. We've all done that - it's a rite of passage. She was nice enough to let me try it, and it's ridiculously good. Of course, now I want one.
Musically, I've been a little uninspired since the Science Revue finished up. I think I'm finally coming out of that, and feeling like playing again. What I'm finding fun at the moment is listening to sax players, and trying to play very simple sax pieces. I read a quote from Richie Blackmore that said in part "The average sax player is much better than the average guitar player". Having played with a few sax players now, I can believe it. But what's more interesting than whether sax players are better or not is that sax players tend to have a different approach than guitar players, and trying to imitate that is helping me break out of my rut. In particular, sax players don't tend to play notes that fall easily under the fingers of a guitar player, so you end up sounding a little different just because of that.
I'd really like to find someone to play with, so maybe I should make that a priority.
http://www.mega-nerd.com/erikd/Blog/CodeHacking/Haskell/learning_haskell.html
Over the last week or so I've been learning Haskell. Unlike a previous attempt to learn Erlang I think this one will actually end up bearing fruit. The main thing that slowed down my attempt to learning Erlang was that I didn't have a task to apply it to that exploited the strengths of the language.
For Haskell I have a task that is ideally suited to the language and plays to its strengths; writing a parser for an Javascript-like language. Just like when I learned Ocaml I am jumping in at the deep end with a difficult problem and learning the language on the way (ie as a side-effect of tackling the task itself).
Normally my tool of choice for this task would be Ocaml and I did in fact start out writing a parser in Ocaml using the Menhir parser generator. Menhir creates a parser from an LR(1) grammar specification where the LR(1) means that the grammar is left recursive and must need no more than one token look-ahead to resolve ambiguities. Over two days of intense hacking I made quite a lot of progress on the grammar and then hit a wall; numerous rather incomprehensible shift/reduce and reduce/reduce warnings plus a part of the grammar (raw XML embedded directly into the source code) which was not context free and for which I could not see any possible way of parsing with only one token look-ahead.
Since I already knew Ocaml, I looked around at some of the other parser generators for Ocaml like Aurochs and PCL. Aurochs uses Parsing Expression Grammar (or Packrat parsing) and seemed interesting, but was rejected because it seemed to gave very little control over the Abstract Syntax Tree it generated. PCL on the other hand was a monadic parser combinator library which is basically a port of Haskell's Parsec library to Ocaml. The main problem I saw with PCL was that it used Monads and lazy evaluation, neither of which are very common in standard Ocaml code. PCL was also rather new and I wasn't sure if it was stable and mature enough for quite an advanced parsing task.
Of course I had been hearing good things about Haskell's Parsec library for a couple of years and decided that this was a good time to give it a try. The interesting thing about Parsec is that it uses lazy evaluation to provide what is effectively infinite token look-ahead. Obviously, a Parsec grammar should be written so that it only uses more than one look-ahead when that is absolutely necessary.
With a bit of googling I found a bunch of examples using Parsec for simple things and that was enough code to get me started. A week later, after an IRC question answered by Don Stewart, a bit of help from Conrad Parker and a question answered on the Haskell Cafe mailing list, I am almost as far along as I got with the Ocaml version of the parser.
My impressions of Haskell and Parsec so far are as follows:
All in all, I'm really enjoying my foray into the world of Haskell.
http://jamespurser.com.au/blog/Sweet%20Potatos_Tomatos_and_YAJZ
I haven't blogged in a little while, so I thought I would do a quick update on the Garden.
First up we have our Cherry Tomatos which are just about ready to pick:

Seeing as Ms 3 is our resident Tomato fiend, she'll have the honour of picking the first batch.
Next we have an update on the Sweet Potato. As you can see it seems to have been a successful planting. The greenery is running riot and there are plenty of roots coming off the old sweet potato:

And finally, it wouldn't be a garden report without YAJZ (Yet Another Jumbo Zuchinni):

http://www.rumble.net/blog/index.cgi/travel/Lunch_in_Coffs.html

http://marty.sunriseroad.net/2008/12/28/switching-to-internode/
Well after a few month’s deliberation, I decided to switch to Internode as my ISP last Tuesday. While I wasn’t unhappy with iinet as a service provider, it really came down to a value-for-money decision. Having 4 teenagers in the house, meant that we seemed to be every month hitting 10+10GB quota I had with iinet. And while some of them could make use of the off-peak download time by scheduling downloads, it really isn’t all that convenient. And all to often it seemed that at least once a month someone would get the time wrong to start or finish downloads so we would have inadvertant creepage into the peak quota. However for the same $70 is was spending at iinet, I could get 40GB monthly quota, with no time restrictions - so hopefully there will be no more draconian filtering by yours truly to keep us under quota.
Internode (like iinet) are very Linux friendly (in that they can provide support for Linux users if required) but more importantly they both provide good unmetered repositories/mirrors of open-source software. Internode seems to have the edge though, especially now they are a Sourceforge mirror. They also have some nice unmetered media with quite a few radio streams. Another clincher for the recent decision was that Internode now provide ABC’s iView unmetered, which all made good use of on iinet. According to my kids the gaming servers are well supported and have low “ping” times, so all should be good on that front. Actually one nice thing the Internode does is publish a very clear list of IP address ranges that are unmetered. I might try to combine this info with the netflow info I have been grabbing from my router to more accurately feedback to my family on their metered/unmetered usage profiles.
We also have made use of iinet’s bundled phone PSTN and VoIP services. However this actually proves to more costly than what it should be. With iinet to get my $70 ADSL plan I needed to bundle the phone service at around $33 (though I got free VoIP access). But with Internode, I can get the $70 ADSL (with 2x quota) and I can buy my phone service from Telstra (I’ll choose the $19 budget plan), and then I can buy a $10 VoIP service which comes with $20 phone credits. All up, I expect to save maybe $20 a month and get double the data quota. Internode by all accounts have a good service reputation, so I really have no qualms in switching.
So I am still happy to recommend iinet for their level of customer service, however despite a few calls to them indicating I was about to leave, and giving them an opportunity to keep me, they really couldn’t match Internode’s pricing.
Hopefully all goes well.
http://certifiedwaif.livejournal.com/335275.html
The room I'm renting is in a house on a semi-major road. Most of the sound seems to be coming in through my window. Does anyone have any ideas? I think heavy curtains might help. The ideal solution would be double glazed windows, but as I'm a renter and don't own the property I'm limited in what I can do.
It looks like I'm about to become an expert in cheaply sound proofing a room.
http://feedproxy.google.com/~r/zhasper/~3/TFXEHcFPCvU/
Okay, so I lied. Some of these are from two days ago..
|
stilgherrian “Christmas ruined as Sarah Palin shoots Rudolph” http://is.gd/cYaU
|
||
|
stilgherrian Just discovered NewsBuiscuit! “Children ‘getting over-excited’ about going to church on Christmas morning”: http://is.gd/d6pz
|
||
|
harleyd I just had to explain who ABC radio host Julie McCrossin was to an ABC reporter who rang seeking gay christian sources. Yay ABC cuts.
|
||
|
mcannonbrookes RT @barconati Awesome post. Dan talks about the benefits of deploying Confluence enterprise wiki at the Powerhouse Museum http://tr.im/2l9b
|
http://certifiedwaif.livejournal.com/334941.html
I've been thinking about how to take my guitar playing further. This year I found that I really enjoyed playing for people, so I'll probably keep looking for opportunities to do that. I guess the short version of what I think I should do is
http://certifiedwaif.livejournal.com/334816.html
My new house mates got Wii Fit for Christmas. They're jogging through a virtual landscape in our living room. So weird.
http://feedproxy.google.com/~r/zhasper/~3/WkqoAtqxup0/
One of the downsides of having spent years messing with my old Drupal blog is that I’ve ended up with a bunch of different permalink styles: to pick three posts at random, http://zhasper.com/zhasper/harry_potter_done, http://zhasper.com/2007/09/linkbloggery, http://zhasper.com/?p=631. Fortunately, I’m only running this blog to give myself a place to vent, so I don’t care about lost traffic. If I did care, this would be a problem.
I’m using the “Platinum SEO pack” plugin, which does a good job of handling URLs that don’t quite match the same schema that Wordpress is using - for instance, if you visit http://zhasper.com/linkbloggery, it’ll figure out that you meant the second URL in the list above. Unfortunately, it’s not perfect - and my old blog had way too many variations for anything to cope with.
So, I’m going through and doing what I can to fix the low-hanging fruit. URLs in the second form, /YYYY/MM/title, already work fine. URLs in the first form need to have the /zhasper/ removed, and need all the _s turned into -s. I accomplish both of these through a bit of RewriteRule magic:
RewriteEngine On
RewriteBase /
RewriteRule zhasper/(.*) /$1 [R=301,L]
RewriteRule (.*)_(.*) $1-$2 [R=301,L]
This is quite definitely not the neatest way to achieve this. In the example above, it requires three excess round-trips between the server and the browser:
The 301 in the RewriteRule means that the server tells the client that this is a permanent redirect - the content will never be at the old address, please update your bookmarks. This doesn’t make much difference to your browser - but crawlers such as Google should use this as a signal to update their index, and send any link-love directed at the old link to the new link.
If you didn’t have the redirect at all, Google wouldn’t know that /zhasper/harry_potter_done and /2007/07/harry-potter-done were the same page - it would think that the latter was just a more-recently-seen page which mysteriously had similar content to the old page.
If you go with a temporary redirect (by just using R on its own, or by stipulating [R=302], Google won’t know to update its index: it will still come back later and check the old URL, just in case the page has moved back there.
There are definitely better ways to achieve this - suggested enhancements are welcome
http://feedproxy.google.com/~r/zhasper/~3/cNTnvGB7dWI/
I’ve seen a few hits on my site to http://zhasper.com/user/, or pages underneath. This seems to be because there used to be content there, and Google’s cache hasn’t (or hadn’t at the time anyway - it seems to have mostly caught up now).
I don’t want this, so I went to the “Remove URLs” tool, under Tools in the Webmaster Console.
The page says:
Before you begin, you must make sure that Google and other search engines will not crawl the content you want to remove from our search results.
To do this, ensure that each page returns an HTTP status code of either 404 or 410, or use a robots.txt file or meta noindex tag to block crawlers from accessing your content.
Okay, so it needs to return a 404. Easy - there’s no content there anyway, it’s already returning a 404. Double-check:
zhasper@bridgitte:~$ wget http://zhasper.com/user/
--2008-12-25 17:03:31-- http://zhasper.com/user/
Resolving zhasper.com... 88.198.1.123
Connecting to zhasper.com|88.198.1.123|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2008-12-25 17:03:31 ERROR 404: Not Found.
Excellent. So, I request the whole directory to be removed from the index.
Some days later, I come back and check, and my request for removal has been denied. There’s a little question mark beside the word denied, obviously further details, so I click on it:
Your request has been denied because the webmaster of the site hasn’t applied the appropriate robots.txt file or meta tags to block us from indexing or archiving this page.
No shit - I didn’t put anything in robots.txt because it’s returning a 404, and your instructions say that’s all that’s needed.
Grrr.
I *think* that everything under /user/ has been removed (there’s certainly nothing in the index any more), it’s just /user that’s not been removed. I don’t understand this - /user gives a 404 also, and the content shown in the snippet is the old Drupal content.
(obdisc: this is a private blog, all opinions are my own and not those of my employer, who happens to be Google. There’s probably something obvious that I’m overlooking - hopefully I’ll have another blog post soon with an update on what that is)
Udpate, 5 minutes later: Duh. Read the next paragraph, idiot:
If you’re requesting removal of a full site or directory, you must use a robots.txt file to block crawlers from accessing this content.
I’m requesting removal of a full directory. So….
http://blog.kfish.org/2008/12/tractorgen-on-github.html
Tractorgen is now on github:
The contents of this revision controlled document repository are a computer source code implementation of TRACTORGEN, being a model of ASCII tractor mechanics. It is recommended that one study these documents closely in order to better understand the finer details of the subject at hand. The authors firmly believe that only through such preparation, preferably during the course of one's daily study regimen, can a deeper appreciation of the theory be attained. As a side note, it has been noted by correspondents that it is possible to derive a computer readable binary executable from these documents through the use of sophisticated compiler technology. On the off chance that any readers would wish to pursue this path, we include the apparent preparation for doing so herein, as quoted: $ automake -a $ autoreconf Upon completion of this procedure, which we expect should take on the order of one to two weeks (of course the actual time depends on the staffing resources of your local computer centre), a new document shall be generated _as though from nought!_ [emphasis added]. The name of this document is expected to be "configure", and it may itself be executed thus: $ ./configure We recommend scheduling a vacation! Upon your return, type "make", then "make install", and prepare your experimental apparati forthwith: $ tractorgen Generates ASCII tractors.
One must eschew the typically terse and perfunctory style of commit messages that are common in software projects, and ensure that the purpose, significance, and experimental procedure for each incremental change are appropriately recorded.
Obviously, commit messages are a good place to store source code for important tools: 9112c05.
r-------
_|
/ |_______\_ \\
| |o|----\\
|_____________\_--_\\
(O)_O_O_O_O_O_(O) \\
http://blog.heimic.net/2008/12/24/just-about-christmas-and-nearly-the-conclusion-to-another-year/
Well it is nearly Christmas, so I thought it would be a good time to make a quick post. Wish everyone a Merry Christmas and a Happy New Year.
Only days away from the conclusion of another year, I can’t believe it. I bet I end up saying something similar this time next year. I am sure everyone will agree the year just goes on by so quickly without much thought of what we had hoped to achieve in the period.
I hadn’t announced it here yet, but now is a good as time as any. For those who don’t know already, my wife and I are having our first child. The baby is due on 5th May at this stage, which is a day shared with another family member who has a birthday on this same day. Soon see if things happen on that day or not.
Have a Merry Christmas.
http://blog.kfish.org/2008/12/release-hogg-041.html
A new release of HOgg, on Hackage:
This contains updates to work with Hackage, the Haskell source package system; and also a new hogg man subcommand to generate man pages for subcommands.
Hackage is Haskell's source packaging system. It makes it very easy to keep up to date with bleeding-edge releases.
You'll need the cabal command. This is already in Gentoo (emerge cabal) and Arch Linux (pacman -S cabal-install). If you're on a system where cabal is not already packaged, you'll first need to install GHC (eg. apt-get install ghc6 on Ubuntu 8.10 or Debian Lenny systems), then:
$ wget http://hackage.haskell.org/packages/archive/cabal-install/0.6.0/cabal-install-0.6.0.tar.gz $ tar zxf cabal-install-0.6.0.tar.gz $ cd cabal-install-0.6.0 $ chmod +x bootstrap.sh $ ./bootstrap.sh
This will download and build the packages required to set up cabal. From there, a new Haskell package like hogg can be installed by simply doing:
$ cabal update $ cabal install hogg
This will build and install hogg into $HOME/.cabal/bin (which of course you should add to your $PATH if you actually want to use anything you install via cabal :-)
hogg already generated its own help text, with runtime checking of example syntax. This release adds a hogg man subcommand which generates the same help text in Unix man page format:
$ hogg man man .TH HOGG 1 "December 2008" "hogg" "Annodex" .SH SYNOPSIS .B hogg .RI man [ .I OPTIONS ] .SH DESCRIPTION Generate Unix man page for a specific subcommand (eg. "hogg man chop") .SH OPTIONS -h, -? --help Display this help and exit -V --version Output version information and exit .SH EXAMPLES .PP Generate a man page for the "hogg chop" subcommand: .PP .RS \f(CWhogg man chop\fP .RE .SH AUTHORS hogg was written by Conrad Parker This manual page was autogenerated by .B hogg man man. Please report bugs to <ogg-dev@xiph.org>
http://jamespurser.com.au/blog/More_Gems
Having three kids, you are always going to hear some wierd and wonderful things and these past seven days have not been any different.
Yesterday I was having a "discussion" with mr 10 about his behaviour and the subject of presents at christmas time came up. He was confident that he would be recieving presents, no matter what his behaviour, when his sister miss 5 decided to pipe in with "You should listen to daddy, he went to school with Santa!".
This however was not the funniest thing we heard from our flock of kinder. A few days ago, we were leaving Wollongong Hospital after visiting Karins dad (who had a stroke last monday, while he's been laid low, it's not as bad as it could have been), and we got stuck at the lights. Karin rocked the car back and forth on the plate in an effort to hurry up the lights. Miss 3 got very cranky when we didn't immediately start driving off and said so "What are we waiting for, a stop go party? Get moving!"
Got to love kids :)
http://feedproxy.google.com/~r/zhasper/~3/b_HY1WhKDU8/
From the normally staid ABC news website comes this gem:
Paranoia is much more common in modern society than previously thought, says a British doctor, who warns it could lead to major problems in society.
Oh noes! Rampant paranoia! Is this what’s been making me think crazy thoughts lately? Our society is in danger! Quick people: we must be vigilant! Examine your own thoughts for any hint of paranoia, NOW!
Dr Daniel Freeman from the psychiatry institute of King’s College London says almost a quarter of the population experience regular paranoid thoughts,
One in four? Then it’s almost certain that I’m paranoid. Woe is me! Whatever could be causing this epidemic of paranoia?
driven by an avalanche of sensational stories in the media.
Oh. Right. Good to see that you’re helping there, doc!
http://airlied.livejournal.com/64021.html
So we merged r500/r600 via atombios TV-out support, but we haven't enabled it by default.
You need to add
Option "ATOMTvOut" "true" to xorg.conf to enable it.
We'll hopefully get to fix up some of the remaining corner cases and issues or enable it at
least on a card by card basis.
http://pipka.org/blog/2008/12/23/moving/
We are moving at the moment. More details on this soon, but if you are trying to get in contact with either of us, please give us aweek or two to get back to you
Otherwise call/sms us if it is urgent.
Moving to the country, gonna eat a lot of peaches.
http://jeremy.visser.name/2008/12/23/takeaway-lights-script/
I just stumbled across a simple yet fun script I wrote over a year ago to animate your keyboard LEDs:
#!/bin/sh LED="setleds -L" SLEEP="sleep 0.2s" $LED -num -caps -scroll if [ "$1" = "-c" ] ; then exit 0 fi while [ 1 ] ; do $LED +num $SLEEP $LED +caps $SLEEP $LED +scroll $SLEEP $LED -num $SLEEP $LED -caps $SLEEP $LED -scroll $SLEEP done
It will simply pulsate the keyboard LEDs from left to right. Note that this script only works while logged into a tty — it does not work under X11.
http://www.technovelty.org/toys/iphone-streaming.html
FStream is a really neat streaming radio program for the iPhone. Although it supports various WMA streams, I found that it did not successfully work with some of the Australian ABC WMA streaming radio services.
The most reliable method seems to simply use a low-bandwidth MP3 stream over HTTP (24 kbps sounds fine and works great even over Edge). I could find a number of other blogs, etc. with static methods for streaming, but nothing that reliably did on-the-fly conversion of an incoming stream.
My solution is simple Python HTTP server I'm calling stream2mp3. It uses mplayer, lame and a few pipes to take the incoming stream (which is pretty much anything mplayer can handle, which is pretty much anything unencrypted) and spit it out as a low-bandwidth MP3 stream over HTTP.
It seems to reliably handle dropped and closed connections, and clean-up after itself. I'd certainly be interested in any bug fixes or suggestions. I guess the major disadvantages is you need a dedicated server (get yourself a linode!), it only handles one connection at a time, and if you want multiple stations I guess you run multiple instances on different ports.
With this, you can be sitting in traffic on the 101 heading to San Francisco and, with some local radio, it's just like you're sitting in traffic on the M2 in Sydney! Here's a screenshot:
~/bin$ python stream2mp3.py Creating WAV fifo /tmp/incoming.wav Creating MP3 fifo /tmp/output.mp3 Serving <mms://media3.abc.net.au/702Sydney> on port XXXX mplayer running as 8524 lame running as 8525 mobile-XXX-XXX-130-107.mycingular.net - - [23/Dec/2008 18:59:22] "GET / HTTP/1.1" 200 - [radio plays until I stop it...] connection lost cleanup complete, ready
http://feedproxy.google.com/~r/zhasper/~3/s2XUJe4gJZ0/
Re censorship of flight details: Tim Bennet at Electron Soup was faster than me and got screengrabs before the details were censored. Go satisfy your curiousity at his blog.
http://certifiedwaif.livejournal.com/334358.html
I've moved share house again - this time from Stanmore to Haberfield. It was sad in a way - I've lived in or near Newtown for five years now.
The move was a marathon effort. My parents are getting older, so rather than try to get my family to help me move, I hired Two Men and Truck. They delivered boxes to me on Thursday, for a move on Sunday morning. I've moved house so many times before that I know that there's no such thing as overpreparation, so with help from friends, particularly Dee and Jack, I tried to pack my entire life into boxes as much as possible before the movers arrived. While I'm glad the process was spread over several days, it was physically tiring and I'm quite drained.
Because I put so much effort and thought into preparing for the move, the actual moving day went off without a hitch. As
thaytan said, professional removalists work fast. The entire contents of my room and study area were packed in under half an hour, and the whole move was completed in two. We drove to Haberfield, they unloaded everything and off they went. Jack and I went back for fragile things like computers, guitars and tube amps later in the day.
The new house is, um, interesting. It's big, and has lots of potential, but also a few quirks. Some highlights - dining room, dishwasher, enormous garden, large rooms. Some parts of the house need some love. I also don't know yet if I'm going to be here very long, because the lease is up in February, and people in the house haven't quite decided what they want to do. But for the time being at least, things are good.
http://jamespurser.com.au/blog/LCA_2009_-_Are_You_Going
Hey guess what, in less than a month one of the best tech conferences in the world is going to be happening in Hobart, are you going to be there? I know I am.
I've been to LCA once before and I have to say it was pretty damn impressive. The gathering of minds and the opportunity to pick the brains of some of the brightest people in our community is almost priceless. Combine that with the fact that it's going to be in the only State I haven't actually been to/lived in, and I couldn't resist.
http://blog.heimic.net/2008/12/22/ubuntu-annoyances/
Downloaded the Ubuntu 8.10 AMD64 alternate image. Proceeded to install. Setup LVM etc, then install continues. It then stops and prompts you to insert another disc. It would appear it wants the Ubuntu 8.10 AMD64 desktop disc. Lucky I have a copy, it then proceeds to not accept it, yet the disc id matches exactly that it is asking for.
Grrr..
http://research.operationaldynamics.com/blogs/andrew/software/java-gnome/cairo-arcs.html
The excellent Cairo graphics library has a simple function to draw arcs; in C it’s cairo_arc(); from java-gnome it’s Context’s arc() method, etc.
Quite unsurprisingly they define increasing angles as going from the positive x axis on toward the positive y axis. Nothing unusual about that. The only thing that was surprising is that they even mention this in their documentation.
I should know better.
What I totally missed was the implication of this. I didn’t quite clue in that the positive y direction in screen positioning and page drawing is down, and so increasing angles go clockwise. Using cr.arc() to go from 0 to say π/3 radians does not give a rise of 60° like I expected; it gives this:

Whoa. This is not the counter-clockwise increasing θ like we’re all used to seeing in normal Cartesian or Polar co-ordinates. But it is indeed increasing toward the positive y axis. Oops. Oh well :)
So I made this illustration and added it to the documentation for Context’s arc() method. Really it’s mostly about pointing out which direction positive y is, but when I’ve learned something like this the hard way, I do my best to try and incorporate that knowledge into our public API. With any luck others can be spared my folly.
Drawn with Cairo, of course!
AfC
Update: Some people have pointed out that you can use a transformation matrix, and if you happen to (say) mirror across the horizontal axis then the clockwise notion would no longer apply. Fair enough; but if you have forgotten that +y starts out going down, then you’re not going to think to do such a flip in the first place.
http://research.operationaldynamics.com/blogs/andrew/travel/germany/rhone-beaune.html

I was pleased to find a decent l’Entrecôte restaurant in east Berlin around the corner from where I was staying.
I ordered what looked like it might be a promising little Côte de Rhône. Somewhat to my chagrin, a bottle of Côte de Beaune showed up instead. Which turned out to be delightful.
Hautes-Côtes De Beaune 2005
“Clos De La Perrière”
Domaine Parigot Père et Fils
Meloisey
Which just goes to show that what you ask for has little to do with what’s actually going to work with the meal you’re having.
AfC
http://bethesignal.org/blog/2008/12/20/more-mainstream-media-love-for-openaustralia/
Totally awesome to see Matthew Moore covering OpenAustralia’s efforts to bring the register of members’ interests to the web:
Given the fortunes spent in the nation’s Parliament, and Kevin Rudd’s professed desired for more transparency in government, it seems absurd that volunteers are left to do the job any self-respecting parliament would have done long ago.
via Interests of MPs to go online - it’s about time.
http://www.rumble.net/blog/index.cgi/geek/Languages_as_religion.html
Perl is indeed like slitting the throat of a live chicken and smearing its blood and entrails on an effigy of your enemy.
If programming languages were religions... thanks to Raz
http://feedproxy.google.com/~r/zhasper/~3/2osnttsNNvg/
Stilgherrian alerted me to the fact that I got a mention on Crikey today - or at least, yesterday’s post about ASA’s censorship of flight records did.
I’m flattered, but also slightly pissed. If you clicked on that link, you’d have been asked to provide your credentials as a paid-up member of Crikey - or at least, to take a 21-day free trial. I had to do the latter, in order to read what had been said. Hopefully if I’m ever mentioned again on Crikey it’ll be within the next few weeks - because after that my free trial will have expired, and I’d hate to have to pay for a membership just to see how I was being quoted. There’s plenty of good reasons to pay for a membership, and I’ve been toying with the idea for a while - but that’s not the reason I’d prefer to be my primary reason.
So yes, I signed up for the trial and got to read the article. There’s a nice link back to my blog - except with a missing “http://”, so the link directs readers to http://www.crikey.com.au/Politics/zhasper.com/2008/12/censorship-of-flight-details/ and not to my blog. So, of course, I got… well, actually, I got 27 people hitting that page directly, no doubt through manually fixing the URL.
Actually, I should say that I got two half-mentions. I also had 61 visits from http://civilair.asn.au/. Ben Sandilands, the journalist wrote the Crikey piece, seems to be active there as well (at least: I found a story from him just by skimming the front page) - I’m guessing the two are related. As with Crikey, I can’t see the content on this site without registering. Unlike Crikey, it’s not possible to register here - so I’m still in the dark about where the traffic came from.
So, overall, a good day for blogging. Apparently I’m not the only person interested in why ASA censored flight details - I just wish I could see what the other interested people are saying.
—
Unrelatedly, I caved and ordered x-plane tonight. If I had a car, I’d be at the airport on one of the mounds right now, having spent the last half-hour watching the last few planes scurrying to get off the ground before curfew kicks in. I seem to be back in *that* phase.
http://blog.heimic.net/2008/12/19/lots-of-screen-resolution-sweet/
Just purchased a Benq E2200HD LCD monitor. It’s a 21.6″ widescreen with 1920 x 1080 resolution. Has d-sub, DVI and HDMI 1.3 inputs.
All I can say is that running at native resolution is unreal. It’s like literally having dual monitors, as the screen resolution is so high.
Will have to hook up the work laptop to it when I am working remote, as it will make life so much easier. Very impressed.
All I need now is for the onboard ATI 3200HD video card to be much more widely supported on Ubuntu/Linux. In the meantime 2D use works well enough so I think a Ubuntu 8.10 desktop install will be in order, as I think a Ubuntu/Linux system would be good on this system. Will then run VMware Workstation for any Windows XP Pro guests I need to use.
Monitor was a good price too, they retail for about $239 - $249 which is a good buy, considering a few years ago my first 17″ analog LCD monitor was $705 or so (which is still going).
http://soniahamilton.wordpress.com/2008/12/19/udev-hal-dbus/
A good post from Glen Turner on SLUG about udev, HAL, DBUS (in the context of GSM modems):
- you insert the device
- UDEV tells HAL that it has been inserted
- HAL looks up a XML-based "information" file. These are where the
rubber hits the road. The system files are in
/usr/share/hal/fdi/
and any files you may write go into
/etc/hal/fdi/
- HAL determines from the USB vendor/model codes it was handed
that you've got a GSM modem. The policy files contain related
details like which USB Serial port to use for PPP, what dialing
algorithm to use, etc.
- HAL pumps these details to NetworkManager, probably via DBUS
- NetworkManager daemon chats with the NetworkManager applet to
grab other data, such as PIN numbers
- NetworkManager kicks off PPP using the combined information
from HAL and the NM applet.

http://certifiedwaif.livejournal.com/334203.html
Every other time I've moved, my parents and brother have helped me, and I've completed the entire move in one day. This basically killed us, especially my mother, and made the moving experience much more stressful. This time, I'm hiring removalists and packing well in advance. We're moving on Sunday, but because I know packing always takes longer than I think, I started yesterday, with help