<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3663284046896592766</id><updated>2012-02-16T21:21:59.489+01:00</updated><category term='linux'/><category term='Fedora'/><category term='gsoc'/><category term='space invaders'/><category term='javascript'/><category term='java'/><category term='programming'/><category term='hiragana'/><category term='sdl'/><category term='music'/><category term='gnu'/><category term='midi'/><category term='freedom'/><category term='stallman'/><category term='free software'/><category term='audio'/><category term='css'/><category term='japanese'/><category term='denmark'/><category term='opengl'/><category term='chipmunk'/><category term='html'/><category term='diku'/><category term='kmemcheck'/><category term='physics'/><category term='jato'/><category term='c++'/><title type='text'>tail -f /var/log/messages | grep vegard</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-5887783516429561506</id><published>2010-01-26T22:28:00.003+01:00</published><updated>2010-01-26T22:40:47.146+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='sdl'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='opengl'/><category scheme='http://www.blogger.com/atom/ns#' term='space invaders'/><title type='text'>Space invaders?</title><content type='html'>After my exams in December, I relaxed by writing a sort of space game using C++/SDL/OpenGL:&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/WV69QoRgoFU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/WV69QoRgoFU&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I ripped the sprites from Space Invaders and Galaga/Galaxian, please forgive me. If whoever wants to play/hack, the source code can be found here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/vegard/spaceinv"&gt;http://github.com/vegard/spaceinv&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The video is a bit poor, mostly because the frame rate is supposed to be 60 FPS, but the Ogg/Theora capture was 25 FPS while the actual gameplay was probably closer to ~10 while doing the capture. Need to fix that. It looks better when playing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-5887783516429561506?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/5887783516429561506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=5887783516429561506' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5887783516429561506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5887783516429561506'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2010/01/space-invaders.html' title='Space invaders?'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-2229423067988246828</id><published>2009-09-10T18:16:00.003+02:00</published><updated>2009-09-10T19:29:18.714+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jato'/><category scheme='http://www.blogger.com/atom/ns#' term='gsoc'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>First Jato release</title><content type='html'>So I somewhat promised to say something more on my project for the Google Summer of Code.&lt;br /&gt;&lt;br /&gt;I participated for the first time, and it was really a great experience. This is the first time I've been paid to do what I would probably have done in either case (because I immensely enjoy it), namely to work on an interesting free software project. So this time it was Jato, a new implementation of the Java Virtual Machine.&lt;br /&gt;&lt;br /&gt;Jato is written in C and aims to be a JIT-only compiler/VM. So before the summer started, it wouldn't run a lot of Java programs. It couldn't even run the trivial "Hello World", but more about that later. It &lt;span style="font-weight: bold;"&gt;could&lt;/span&gt; do a few things like (java.lang.)String operations, but that was mostly because it was riding piggyback on another VM, Jam VM, which would load classes and interpret a lot of the library code (i.e. most of the standard Java API implemented by GNU Classpath).&lt;br /&gt;&lt;br /&gt;My own project was to replace the parts that were borrowed from Jam VM with completely new, shiny code. Well, in fact, I had already worked on a standalone library called cafebabe, which would parse the Java .class file and present it to C programs using a very thin layer of structs -- the idea was to do as little as possible with the actual data and just make it easily accessible, e.g. so cafebabe doesn't do any verification of the bytecode or make sure that a class is its own superclass.&lt;br /&gt;&lt;br /&gt;So we linked this library with Jato, and that worked pretty well. (I believe strongly in modularisation; with the class loader in a separate library, there's no way to do stupid things like making the class loader itself depend on the rest of the VM for functioning properly.) There were problems, of course, the biggest being that after developing in my own private branch for a couple of weeks, the rest of the project with its three other GSoC student participants was moving ahead too quickly for me to keep up; I had to "fix" just about every new mainline commit, since most of the VM data structures (classes, methods, fields) now had different names, different fields, etc.&lt;br /&gt;&lt;br /&gt;At around this point, we started to notice that Jam VM wasn't being used for nearly as little as just class loading. In fact, static initializers (the "&amp;lt;clinit&amp;gt;" methods) and their calls were all being interpreted and executed by Jam VM, not the JIT compiler of Jato. And of course, once we started using Jato for those methods which had previously been executed by Jam VM, we found tons of bugs everywhere: The core VM (mostly my code replacing that of Jam VM), including improperly implemented Java semantics, missing bytecode instruction handlers, and the compiler (instruction selection, liveness analysis, register allocation). But it was fun, and extremely educative.&lt;br /&gt;&lt;br /&gt;Did you know that a simple System.out.println() will make a whopping 650550 Java-method calls? That's using GNU Classpath for the Java API.&lt;br /&gt;&lt;br /&gt;So we had to implement a lot of stuff just to make that work. In fact, we have so much infrastructure that we can even run a few other programs. And thus it was decided that it was time to make a release. The version 0.0.1 announcement:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thread.gmane.org/gmane.comp.java.vm.jato.devel/1725"&gt;http://thread.gmane.org/gmane.comp.java.vm.jato.devel/1725&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The "next big" missing feature is garbage collection. I expect that'll be version 0.0.2. In other words, if you're interested in Java, garbage collection, or just compilers in general, you're welcome to join us...&lt;br /&gt;&lt;br /&gt;Our team consisted of:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Pekka Enberg; Original creator, project manager and mentor.&lt;/li&gt;&lt;li&gt;Tomek Grabiec; His original project proposal included implementing exception handling, but he ended up somwhat like Ingo Molnar of the Linux kernel; Tomek also implemented a generic radix tree, implemented the basic threading support (java.lang.Thread), rewrote large parts of the register allocator, wrote the VM side of the JNI interface from scratch, and also did a lot of other core-VM work. Tons of other things too, including a lot of debugging.&lt;/li&gt;&lt;li&gt;Arthur Huillet; Floating-point support, register allocator fixes, other missing bytecodes, also a lot of debugging. Various other things.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Eduard-Gabriel Munteanu; Ported Jato mostly to x86-64. A tough task, since the i386 parts were moving at close to light speed.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-2229423067988246828?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/2229423067988246828/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=2229423067988246828' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2229423067988246828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2229423067988246828'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/09/first-jato-release.html' title='First Jato release'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-6729164969148998803</id><published>2009-09-10T17:59:00.005+02:00</published><updated>2009-09-10T18:16:21.141+02:00</updated><title type='text'>The Jato IRC logger</title><content type='html'>Here's the recipe for the Jato IRC logger. Nothing fancy, but works surprisingly well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/home/vegard/jato-irc-logger/irssi-config&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;settings = {&lt;br /&gt;       core = {&lt;br /&gt;               real_name = "#jato IRC logger";&lt;br /&gt;               user_name = "vegard";&lt;br /&gt;               nick = "jato-irc-logger";&lt;br /&gt;       };&lt;br /&gt;&lt;br /&gt;       "fe-text" = {&lt;br /&gt;               actlist_sort = "refnum";&lt;br /&gt;       };&lt;br /&gt;&lt;br /&gt;       "fe-common/core" = {&lt;br /&gt;               autolog = "Yes";&lt;br /&gt;               autolog_path = "logs/$0/%Y-%m-%d.txt";&lt;br /&gt;       };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;servers = (&lt;br /&gt;       {&lt;br /&gt;               address = "irc.freenode.net";&lt;br /&gt;               chatnet = "Freenode";&lt;br /&gt;               port = "6667";&lt;br /&gt;               autoconnect = "Yes";&lt;br /&gt;       },&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;chatnets = {&lt;br /&gt;       Freenode = {&lt;br /&gt;               type = "IRC";&lt;br /&gt;               autosendcmd = "/^msg nickserv identify vegard &lt;span style="font-style: italic;"&gt;password&lt;/span&gt;";&lt;br /&gt;       };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;channels = (&lt;br /&gt;       {&lt;br /&gt;               name = "#jato";&lt;br /&gt;               chatnet = "Freenode";&lt;br /&gt;               autojoin = "Yes";&lt;br /&gt;       },&lt;br /&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/home/vegard/jato-irc-logger/&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;screenrc&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;screen irssi --config=irssi-config&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/home/vegard/jato-irc-logger/&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;start-logger.sh&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;#! /bin/bash -e&lt;br /&gt;&lt;br /&gt;screen -c screenrc -dmS jato-irc-logger&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;crontab&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;# m h  dom mon dow   command&lt;br /&gt;0 * * * * rsync -r -t --chmod=a+r jato-irc-logger/logs/#jato/ vegardno@&lt;span style="font-style: italic;"&gt;hostname&lt;/span&gt;:www_docs/jato-irc-logs&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;/etc/rc.local&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;#!/bin/sh -e&lt;br /&gt;&lt;br /&gt;cd /home/vegard/jato-irc-logger&lt;br /&gt;sudo -u vegard ./start-logger.sh &amp;amp;&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-6729164969148998803?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/6729164969148998803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=6729164969148998803' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6729164969148998803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6729164969148998803'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/09/jato-irc-logger.html' title='The Jato IRC logger'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-1650332940831064817</id><published>2009-06-17T14:29:00.002+02:00</published><updated>2009-06-17T15:19:51.146+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kmemcheck'/><category scheme='http://www.blogger.com/atom/ns#' term='denmark'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='diku'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>kmemcheck in mainline</title><content type='html'>First of all, I should say that on April 22, I went to Denmark to give a talk on kmemcheck. I was invited to DIKU (Datalogisk Institut på Københavns Universitet) by Julia Lawall, who held a &lt;a href="http://www.diku.dk/hjemmesider/ansatte/julia/cocciwk.html"&gt;workshop on Coccinelle&lt;/a&gt; (or, more generally, "finding bugs in operating system software"). It was really nice to be there, not (just) because I got a chance to talk about kmemcheck, but because I learned so much from all the other talks! Feel free to check out &lt;a href="http://www.diku.dk/hjemmesider/ansatte/julia/cocciwk/nossum.pdf"&gt;my slides&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I had asked my university (the University of Oslo) beforehand to sponsor the trip in exchange for a trip report, but I got no reply to my e-mail. I guess they don't see any value in collaboration with universities abroad.&lt;br /&gt;&lt;br /&gt;And now, for the news: Yesterday, &lt;a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b3fec0fe35a4ff048484f1408385a27695d4273b"&gt;kmemcheck was merged in mainline Linux&lt;/a&gt;! It is quite an incredible feeling after having spent so much time to make it work properly... (Not to mention the rebase marathon that ensued after &lt;a href="http://lkml.org/lkml/2009/6/12/562"&gt;Linus initially rejected it&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;I had also asked Redpill Linpro (a Norwegian/Swedish open source developer) beforehand to sponsor my work on kmemcheck for the summer, but they apparently weren't interested. At least I got a polite reply. (Instead, I got a stipend from Google for working on Jato for the summer, but more on that in a later post!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-1650332940831064817?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/1650332940831064817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=1650332940831064817' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1650332940831064817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1650332940831064817'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/06/kmemcheck-in-mainline.html' title='kmemcheck in mainline'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-786136530993901074</id><published>2009-05-21T00:10:00.004+02:00</published><updated>2009-05-21T00:17:52.924+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='japanese'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='hiragana'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Hiragana tutor</title><content type='html'>An evening spent with Unicode charts, HTML, CSS, and JavaScript resulted in this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://folk.uio.no/vegardno/hiragana.html"&gt;The online Hiragana tutor&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you find any errors, please tell me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-786136530993901074?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/786136530993901074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=786136530993901074' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/786136530993901074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/786136530993901074'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/05/hiragana-tutor.html' title='Hiragana tutor'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-3551959136558565049</id><published>2009-05-05T11:38:00.002+02:00</published><updated>2009-05-05T12:24:21.021+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='midi'/><category scheme='http://www.blogger.com/atom/ns#' term='music'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='audio'/><title type='text'>LADSPA</title><content type='html'>Hurrah for LADSPA.&lt;br /&gt;&lt;br /&gt;I started (yet another) project, this time it's a sort of audio synthesisizer and sequencer library. I've always been fascinated with digital audio, since there are so many cool things we can do with it! Like e.g. create and apply filters, warp the sound waves any way we want, add cool effects, and generally do things that I can't otherwise do. Not to mention that I like music... but who doesn't? :-)&lt;br /&gt;&lt;br /&gt;My program isn't revolutionary in any way; in fact, the short story is that the program tries to "simulate" the way real, analogue audio components can be put together, as e.g. an effect rack (the guitar connects into a distortion module, which connects into a reverb module, which connects to the amplifier, which connects to a mixer board, which connects to the speakers, etc.). I stole most of the concepts from an existing non-free (but very nice) program called Reason [&lt;a href="http://www.propellerheads.se/"&gt;http://www.propellerheads.se/&lt;/a&gt;]. I'm sure there are also free programs that do what I'm trying to do (but part of the fun is doing it myself).&lt;br /&gt;&lt;br /&gt;One really nice thing is that there exist a lot of free plugins that do most of the work when it comes to synthesizing instruments and applying effects. These plugins are implemented using a free library, called LADSPA (Linux Audio Developer's Simple Plugin API) [&lt;a href="http://www.ladspa.org/"&gt;http://www.ladspa.org/&lt;/a&gt;], which is the interface between host programs (such as the one I'm making, but also others, like Audacity) and the plugins.&lt;br /&gt;&lt;br /&gt;So the plugins form a directed, acyclic graph, where the nodes with no outgoing edges are the speakers (or, well, sound card), and the leaf nodes are typically synthesizers (instruments). Arranging the plugins in this way is a really nice thing, because it ensures that there are no vicious feedback cycles (if we really want some kind of feedback, like reverb, we can implement it as a plugin!) It also means that we can do a topological sort to find the order in which the plugins are to be "run".&lt;br /&gt;&lt;br /&gt;Anyway, I've implemented these plugins for my program: A LADSPA plugin wrapper, so we can load any LADSPA plugin as a plugin for my program. An ALSA playback plugin for playing audio in real time. A WAV playback plugin for streaming to disk using libsndfile, which supports a few more formats beside WAV, by the way. A MIDI input sequencer, which reads MIDI files and presents the notes as "control output" to the synthesizer plugins. A mixer plugin, which simply combines several inputs into one output.&lt;br /&gt;&lt;br /&gt;It would probably be possible to create an ALSA capture plugin for capturing audio in real time as well. That would be pretty cool, and we'd have a software guitar amp in no time. There seems to be a problem with using blocking ALSA streams, though, because the application sleeps while the sound card is playing the data, and we're left with almost no CPU-time to actually synthesize the sound. This can probably be solved using threads, though.&lt;br /&gt;&lt;br /&gt;Anyway, I made something cool (I think, anyway), by hooking the CMT organ [&lt;a href="http://www.ladspa.org/cmt/"&gt;http://www.ladspa.org/cmt/&lt;/a&gt;] to a plate reverb [&lt;a href="http://plugin.org.uk/"&gt;http://plugin.org.uk/&lt;/a&gt;], and feeding some classical pieces into the MIDI sequencer (which now supports polyphonic songs!):&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://folk.uio.no/vegardno/output3-KV331_3_RondoAllaTurca.ogg"&gt;Mozart's "Rondo Alla Turca"&lt;/a&gt;&lt;a href="http://folk.uio.no/vegardno/output3-KV331_3_RondoAllaTurca.ogg"&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://folk.uio.no/vegardno/output2-toccata1.ogg"&gt;Bach's "Toccata et Fuga"&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Will probably work some more on this, try to write some plugins (I have a few ideas), actually implement error handling (oops), and try to add the missing fundamental features (like reading the correct MIDI tempo, stop output at the end of the MIDI file, etc.).&lt;br /&gt;&lt;br /&gt;One of the goals of the library is to be small and efficient, and not accept inferior solutions because they're easier to implement (some trade-offs are allowed). The next major feature will probably be to add multi-core support using pthreads, so that all CPU cores can be utilized.&lt;br /&gt;&lt;br /&gt;The code itself can be found at github (as usual): &lt;a href="http://github.com/vegard/trick2"&gt;http://github.com/vegard/trick2&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-3551959136558565049?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/3551959136558565049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=3551959136558565049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/3551959136558565049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/3551959136558565049'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/05/ladspa.html' title='LADSPA'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-1765143452162114389</id><published>2009-04-06T15:23:00.004+02:00</published><updated>2009-04-06T15:53:51.842+02:00</updated><title type='text'>Linux kernel 2.6.27 exploits</title><content type='html'>I found two exploits of the Linux kernel back in January.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://userweb.kernel.org/%7Evegard/exploits/inotify4.c"&gt;The first one&lt;/a&gt; is a crash in inotify, where a locking imbalance would unlock the inotify mutex twice before returning to userspace. It happens only if the buffer passed to read() was an invalid userspace address. It's fixed in mainline and went into -stable last month (if I recall correctly), though I can't say the fix has showed up in the Fedora kernel yet. The result is usually a BUG in the kernel log with list corruption. The system is mostly unusable afterwards, probably because the program is holding some lock at the time that it is terminated by the kernel. So it's a local DOS.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://userweb.kernel.org/%7Evegard/exploits/splice.c"&gt;The second one&lt;/a&gt; is a deadlock in splice() code, which happens because splice needs to lock two mutexes, and it needs to drop them at one point too. So with two or more threads executing concurrently, they may grab them in opposite order. Oops. The result is that the process hangs as an unkillable zombie. This may or may not be so bad. If you run the exploit several times, you can end up with any number of zombies, and for some reason I don't know, zombies count in the load average, so with, say, 20 zombies, the load will rise up to around 20 (even though these processes don't &lt;span style="font-style: italic;"&gt;actually&lt;/span&gt; use the CPU). I guess this makes for a nice local DOS, though. I tried to submit a fix, but it didn't make it to mainline (or -stable, or any other distribution that I know of) yet. It doesn't seem that anybody else is working on a fix either.&lt;br /&gt;&lt;br /&gt;I guess the moral of the story is to review existing kernel code (as well as new patches), because it &lt;b&gt;isn't actually&lt;/b&gt; perfect. I found these exploits by reading the source code and writing some test programs to test my theories, and I can testify that this method works well for finding errors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-1765143452162114389?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/1765143452162114389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=1765143452162114389' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1765143452162114389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1765143452162114389'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/04/linux-kernel-2627-exploits.html' title='Linux kernel 2.6.27 exploits'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-5595235483506730260</id><published>2009-03-21T00:29:00.002+01:00</published><updated>2009-03-21T01:41:26.945+01:00</updated><title type='text'>My brain is open</title><content type='html'>This week was &lt;a href="http://www.dana.org/brainweek/"&gt;Brain Awareness Week&lt;/a&gt;. I found that my university was giving some lectures on the brain, so I attended them all. As expected, it was quite interesting. I knew the basic concepts from before, but it really helps to hear different people talk about different subtopics, as it gives me a fuller picture of how this wonderful organ works.&lt;br /&gt;&lt;br /&gt;In any case, I couldn't help feeling inspired, so yesterday I started writing my very own brain simulator. No, it doesn't really do all that much. But here's what it &lt;b&gt;does&lt;/b&gt; do:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Implements a brain using a neural network. The neural network is actually just a fully connected, weighted graph, where the weights represent the strengths of the synapses. The neural network is currently static (it remains unchanged during the lifetime of the organism), and the model is extremely simple. It supports two types of neurones, excitatory and inhibitory neurones, but that's about it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implements an environment for the brain, e.g. a body and a physical world with which the creature can interact. Actually, this particular environment consists of an empty space (no gravity), and a target, which, when touched by the creature, regenerates in a different position. The body of the creature has two sensors (relative position, i.e. distance to the target and relative velocity, i.e. the speed at which we are moving towards the target) and four outputs. Each of the four outputs can be thought of as a jet pack that can be used to accelerate the creature in a particular direction (up, down, left, right). &lt;br /&gt;&lt;br /&gt;This creature's purpose in life is therefore, as you might have guessed, to reach targets.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I've been using two programs to simulate my worlds, these are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The "evolver": This program is responsible for developing the "genes" of the creature. Those genes are actually just the NxN matrix that represents the neural network graph (where N is the number of neurones, or nodes in the graph). It works quite simply by randomizing the genes and running a simulation with a creature that has this brain. By checking the number of times that the creature reaches the target (each simulation runs only a fixed number of steps), we have a measure of how successful that particular set of genes is.&lt;br /&gt;&lt;br /&gt;When we have found a reasonable brain configuration (e.g. a creature that can reach a target in around 2-3% of the simulations), we start duplicating it and perturbing the configuration slightly. In this way, we have, in each generation, a set of brain configurations corresponding to the original brain plus nine different variations of the original brain. Now each of the brain configurations are given their chances to reach their targets; the most successful configuration becomes the parent of the next generation of creatures. And we have evolution!&lt;br /&gt;&lt;br /&gt;It actually took about 8 hours to find the configuration of the creature that is shown in the video below.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The "player": This program will run a simulation, but also display it on the screen. By default, it uses the most successful brain configuration found so far. This program is what generated the video below. There's not much more to it; the simulation is &lt;i&gt;exactly&lt;/i&gt; the same as in the "evolver". (But without visualization, the evolver can run much faster.)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So without much further ado, here's the result:&lt;br /&gt;&lt;br /&gt;&lt;object width="445" height="364"&gt;&lt;param name="movie" value="http://www.youtube.com/v/6w7o3OYN0jg&amp;hl=en&amp;fs=1&amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/6w7o3OYN0jg&amp;hl=en&amp;fs=1&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Notice how it often overshoots a little. A problem with an earlier brain configuration was that it would start circling around the target in bigger and bigger orbits, eventually disappearing from the screen altogether. I think it's &lt;b&gt;really&lt;/b&gt; interesting, though, to see that it &lt;b&gt;actually works&lt;/b&gt;. It surprised me.&lt;br /&gt;&lt;br /&gt;The source code for these programs can be found at the &lt;a href="http://github.com/vegard/openbrain"&gt;GitHub project website&lt;/a&gt;. I'm not really planning to make a project out of this (other than what you see here), but patches are welcome, as always :-) Source code is GPL version 2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-5595235483506730260?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/5595235483506730260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=5595235483506730260' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5595235483506730260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5595235483506730260'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/03/my-brain-is-open.html' title='My brain is open'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-2596669033775493121</id><published>2009-03-15T15:54:00.007+01:00</published><updated>2009-03-15T18:40:42.133+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chipmunk'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='opengl'/><category scheme='http://www.blogger.com/atom/ns#' term='physics'/><title type='text'>Chipmunk experiments</title><content type='html'>I've been playing with &lt;a href="http://wiki.slembcke.net/main/published/Chipmunk"&gt;Chipmunk&lt;/a&gt; lately. It is a C library that simulates physics in two dimensions, and is intended for use in games. It's quite easy to use, but there is a bit of overhead in setting up graphics since I have to do that on my own. I'm using OpenGL through the SDL library, and it works quite smoothly. Here is the result of today's dabbling:&lt;br /&gt;&lt;br /&gt;&lt;object height="364" width="445"&gt;&lt;param name="movie" value="http://www.youtube.com/v/f_EOozMyCCA&amp;amp;hl=en&amp;amp;fs=1&amp;amp;border=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/f_EOozMyCCA&amp;amp;hl=en&amp;amp;fs=1&amp;amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="364" width="445"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;There are two important fundamental concepts in Chipmunk: &lt;span style="font-style: italic;"&gt;Bodies&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;collision shapes&lt;/span&gt;. What is the difference? A body has the usual properties like mass, position, velocity, etc. However, a body does &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; have an area (a shape). That is the purpose of collision shapes. A collision shape does not have any of the properties of a body, it merely defines a shape (such as a circle or a rectangle). The relationship between these two concepts is that multiple shapes can be attached to a body. Only shapes can collide; bodies do not collide by themselves.&lt;br /&gt;&lt;br /&gt;The balls in the video above were constructed using one collision shape (a circle shape) for each of the three bodies. They were rendered using an 8x8 OpenGL 2D texture (loaded from a PNG image) on a quadrilateral (GL_QUADS). Easy as pie.&lt;br /&gt;&lt;br /&gt;The rope was more difficult to make. For a long time, the rope would either disintegrate slowly (because it was being pulled apart by gravity), or explode (the line segments would vibrate quite violently).&lt;br /&gt;&lt;br /&gt;When making the rope, we need another fundamental Chipmunk object: The &lt;span style="font-style: italic;"&gt;joint&lt;/span&gt;. Joints are used as constraints in the simulation. A constraint is something that keeps an object from moving freely. There are different kinds of joints: Pin joints, slide joints, pivot joints, and groove joints. For example, the pin joint simply stitches together two bodies at certain offsets from the body's centre. When one body moves, the joint will cause the other to follow.&lt;br /&gt;&lt;br /&gt;My rope uses slide joints. The only difference from a normal pin joint is that the joint allows a certain flexibility: The "stitch" can be given a minimum and a maximum length, so that the bodies can get closer together or further apart before the joint's constraint takes effect. We can easily imagine the maximum length property as that of a string connecting two objects. The string will keep the objects from getting too far apart, but it will also bend if the objects are closer together than the length of the string.&lt;br /&gt;&lt;br /&gt;The slide joints connect the line segments of the rope. Each line segment consists of four collision shapes attached to a single body. The four collision shapes are all circles, laid out side by side. These four circles have fixed positions with regards to each other. They're not actually drawn as circles, but as solid rectangles (GL_QUADS). The rope has 30 such line segments, so that's 30 bodies and 120 collision shapes.&lt;br /&gt;&lt;br /&gt;Finally, we have two fixed bodies at either end of the rope. These bodies have infinite mass, are not affected by gravity, and have no collision shapes. (Actually, they're not added to the Chipmunk &lt;span style="font-style: italic;"&gt;space&lt;/span&gt;, so they are not affected by any forces at all.) This is what keeps the rope in place. And to my great surprise, the way in which these bodies are connected to the rope seems to be what determines the quality of the simulation. At first, I was using pin joints to connect these stationary bodies to the endpoints of the rope. It wasn't until I replaced them with slide joints that the rope actually got as smooth as it is in the video above.&lt;br /&gt;&lt;br /&gt;I'm currently toying with the idea of putting a cart with wheels on the thread and controlling the wheels with the arrow keys. If that works, I think it could make for a nice game element as a variation on the paddle of e.g. &lt;a href="http://en.wikipedia.org/wiki/Breakout"&gt;Breakout&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Update&lt;/i&gt;:&lt;br /&gt;&lt;br /&gt;&lt;object width="445" height="364"&gt;&lt;param name="movie" value="http://www.youtube.com/v/IC8yAROqLJA&amp;hl=en&amp;fs=1&amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/IC8yAROqLJA&amp;hl=en&amp;fs=1&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-2596669033775493121?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/2596669033775493121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=2596669033775493121' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2596669033775493121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2596669033775493121'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/03/chipmunk-experiments.html' title='Chipmunk experiments'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-8392780558154859756</id><published>2009-02-24T02:00:00.001+01:00</published><updated>2009-02-24T02:04:18.489+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gnu'/><category scheme='http://www.blogger.com/atom/ns#' term='stallman'/><category scheme='http://www.blogger.com/atom/ns#' term='free software'/><category scheme='http://www.blogger.com/atom/ns#' term='freedom'/><title type='text'>"Happy hacking"</title><content type='html'>Richard M. Stallman was at the university (University of Oslo) today, and he gave a talk titled "Copyright vs. Community in the Age of Computer Networks - Free software and beyond". I was there, of course. It was an interesting topic, though I cannot say that I agree with everything he stands for.&lt;br /&gt;&lt;br /&gt;He explained about the Four Freedoms of the Free Software Foundation [http://www.gnu.org/philosophy/free-sw.html], in short:&lt;br /&gt;&lt;br /&gt;0. The freedom to run the program.&lt;br /&gt;1. The freedom to study and modify the program.&lt;br /&gt;2. The freedom to distribute the program.&lt;br /&gt;3. The freedom to redistribute your modified program.&lt;br /&gt;&lt;br /&gt;He also talked briefly about the history of copyright, to give a background for the origin of copyright law in the first place. Again, in short:&lt;br /&gt;&lt;br /&gt;Question: Why do we have copyright at all?&lt;br /&gt;Answer: To encourage the creation of "works" that benefit the society as a whole.&lt;br /&gt;&lt;br /&gt;Then he compared this original role of copyright law with how it is used in practice today -- or perhaps misused. According to Stallman, copyright law is something that the "megacorporations" abuse in order to squeeze as much money out of the consumer market as possible. It is used for the benefit of these megacorporations by exploiting the rest of the society.&lt;br /&gt;&lt;br /&gt;With this background, he went on with a proposal for the future laws of copyright. The most interesting point was this:&lt;br /&gt;&lt;br /&gt;* Things like software, recipes (for food, which are shared freely among cooks anyway -- paraphrased), and works of documentation (such as encyclopedias, dictionaries, etc.) should all be outside the scope of copyright law.&lt;br /&gt;&lt;br /&gt;(There were also proposals for shortening the copyright duration, e.g. for books of fiction, to, say, 10 years.)&lt;br /&gt;&lt;br /&gt;And this is the point where I actually disagree -- above all the Four Freedoms is a more fundamental one: The freedom to decide whether you want to give away your program's source code, or whether you want to sell only the license to run a program (which cannot be inspected or modified at will).&lt;br /&gt;&lt;br /&gt;I agree that Free Software _is_ superior to proprietary software (I mean as a model, not in the quality of the software itself). But we should not force this on anybody through laws. If I want to sell my compiled program, then I should be able to do that. If I want to sell my book of fiction, I _should_ be able to do it and have the right to stop others from redistributing it. More importantly, if somebody wants to buy my book of fiction and comply with my terms, then they should be able to do that!&lt;br /&gt;&lt;br /&gt;If we must disallow proprietary software in order to have "freedom", then that freedom is not worth it. If Free Software must defend its existence, then it should do so by appealing to its users, not by changing the laws in disfavour of proprietary software.&lt;br /&gt;&lt;br /&gt;It's a bit like Meno's paradox: "You can neither search for what you know, because you would already know it. Nor for what you don't know, because you would not know for what you are looking."&lt;br /&gt;&lt;br /&gt;How can the laws be changed if people don't support Free Software to begin with? And, assuming that they do, there would be no reason to change the law, because they would already have discarded proprietary software of their own, free will.&lt;br /&gt;&lt;br /&gt;I think that we would be much better off concentrating only on why the Freedoms are beneficial for society, rather than trying to change the laws and forcing the Freedoms upon us. And we are really lucky, because we currently have that choice. And many people have made their decision already -- including me.&lt;br /&gt;&lt;br /&gt;Now, there is one more thing I would like to add to the discussion, and that is not about software, but about other kinds of works, like motion pictures and fiction litterature. I think the same principles should apply here: You shouldn't have the right to make unauthorized copies of a book you've bought (much less of books you haven't bought). If you don't respect the license of the author, you simply don't have the right to own a copy of the work in the first place.&lt;br /&gt;&lt;br /&gt;I agree that this is hard to enforce in practice -- illegal file sharing over the Internet can never be stopped, because of the nature of the Internet. And this medium is not very likely to disappear either. All we can hope for, and I believe that this will happen, is that authors and artists will do the same thing that programmers have been doing for two decades now -- to give their works away gratis.&lt;br /&gt;&lt;br /&gt;Of course, there are people doing this already, for example by distributing their works by the Creative Commons family of licenses. But still, the amount of such, we could say "free content", is not even close to that of "commercial content". And how can we change that? How can we make artists and authors give away their hard work for free, and how can we create communities where free content is valued more than commercial content, much like we have communities where Free Software is valued more than proprietary software? Now THAT is something I think we could do to combat the so-called "digital piracy".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-8392780558154859756?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/8392780558154859756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=8392780558154859756' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/8392780558154859756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/8392780558154859756'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/02/happy-hacking.html' title='&quot;Happy hacking&quot;'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-5568055895227065871</id><published>2009-01-25T23:17:00.004+01:00</published><updated>2009-01-25T23:42:13.229+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Bloat</title><content type='html'>Dear Gnome,&lt;br /&gt;&lt;br /&gt;This is completely ridiculous. According to top, "clock-applet" is using 353M virtual memory, of which 17M is resident. I have no swap partition, so it really makes me wonder why those 336M were allocated in the first place. If they are not resident, and not in swap, what are they? Blank pages? mmap()ed files which can be swapped in on demand?&lt;br /&gt;&lt;br /&gt;There is also a column for "shared memory", which says 12M. Does that mean that 12M out of those 353M are shared with one or more other processes? What is this shared memory, library code and mmapped files?&lt;br /&gt;&lt;br /&gt;Isn't 17M also too much for "clock-applet"? It should be one of the simplest applications that run on my desktop. It would be interesting to know what all of this memory is used for. I think that most of it is library code. And here's an indication...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ ldd /usr/libexec/clock-applet&lt;br /&gt; linux-vdso.so.1 =&gt;  (0x00007fffb1fff000)&lt;br /&gt; libpanel-applet-2.so.0 =&gt; /usr/lib64/libpanel-applet-2.so.0 (0x000000000062c000)&lt;br /&gt; libX11.so.6 =&gt; /usr/lib64/libX11.so.6 (0x000000000083b000)&lt;br /&gt; libXau.so.6 =&gt; /usr/lib64/libXau.so.6 (0x0000000000b46000)&lt;br /&gt; libgnomeui-2.so.0 =&gt; /usr/lib64/libgnomeui-2.so.0 (0x0000000000d48000)&lt;br /&gt; libSM.so.6 =&gt; /usr/lib64/libSM.so.6 (0x0000000000fe2000)&lt;br /&gt; libICE.so.6 =&gt; /usr/lib64/libICE.so.6 (0x0000000004d22000)&lt;br /&gt; libbonoboui-2.so.0 =&gt; /usr/lib64/libbonoboui-2.so.0 (0x0000000006c5b000)&lt;br /&gt; libgnomevfs-2.so.0 =&gt; /usr/lib64/libgnomevfs-2.so.0 (0x00000000011ea000)&lt;br /&gt; libgnomecanvas-2.so.0 =&gt; /usr/lib64/libgnomecanvas-2.so.0 (0x00000000064a7000)&lt;br /&gt; libart_lgpl_2.so.2 =&gt; /usr/lib64/libart_lgpl_2.so.2 (0x00000000060ef000)&lt;br /&gt; libecal-1.2.so.7 =&gt; /usr/lib64/libecal-1.2.so.7 (0x00000000077c7000)&lt;br /&gt; libedataserverui-1.2.so.8 =&gt; /usr/lib64/libedataserverui-1.2.so.8 (0x0000000001c1c000)&lt;br /&gt; libebook-1.2.so.9 =&gt; /usr/lib64/libebook-1.2.so.9 (0x0000000001453000)&lt;br /&gt; libgnome-2.so.0 =&gt; /usr/lib64/libgnome-2.so.0 (0x00007f61a9ca3000)&lt;br /&gt; libpopt.so.0 =&gt; /lib64/libpopt.so.0 (0x00007f61a9a99000)&lt;br /&gt; libedataserver-1.2.so.11 =&gt; /usr/lib64/libedataserver-1.2.so.11 (0x00007f61a986f000)&lt;br /&gt; libsoup-2.4.so.1 =&gt; /usr/lib64/libsoup-2.4.so.1 (0x00007f61a962b000)&lt;br /&gt; libbonobo-2.so.0 =&gt; /usr/lib64/libbonobo-2.so.0 (0x00007f61a93b6000)&lt;br /&gt; libbonobo-activation.so.4 =&gt; /usr/lib64/libbonobo-activation.so.4 (0x00007f61a919b000)&lt;br /&gt; libORBit-2.so.0 =&gt; /usr/lib64/libORBit-2.so.0 (0x00007f61a8f2c000)&lt;br /&gt; libgthread-2.0.so.0 =&gt; /lib64/libgthread-2.0.so.0 (0x00007f61a8d27000)&lt;br /&gt; librt.so.1 =&gt; /lib64/librt.so.1 (0x00007f61a8b1e000)&lt;br /&gt; libglade-2.0.so.0 =&gt; /usr/lib64/libglade-2.0.so.0 (0x00007f61a8905000)&lt;br /&gt; libxml2.so.2 =&gt; /usr/lib64/libxml2.so.2 (0x00007f61a85a8000)&lt;br /&gt; librsvg-2.so.2 =&gt; /usr/lib64/librsvg-2.so.2 (0x00007f61a8373000)&lt;br /&gt; libdbus-glib-1.so.2 =&gt; /usr/lib64/libdbus-glib-1.so.2 (0x00007f61a8153000)&lt;br /&gt; libgconf-2.so.4 =&gt; /usr/lib64/libgconf-2.so.4 (0x00007f61a7f15000)&lt;br /&gt; libpolkit-gnome.so.0 =&gt; /usr/lib64/libpolkit-gnome.so.0 (0x00007f61a7d0a000)&lt;br /&gt; libpolkit-dbus.so.2 =&gt; /usr/lib64/libpolkit-dbus.so.2 (0x00007f61a7afe000)&lt;br /&gt; libpolkit-grant.so.2 =&gt; /usr/lib64/libpolkit-grant.so.2 (0x00007f61a78f3000)&lt;br /&gt; libgtk-x11-2.0.so.0 =&gt; /usr/lib64/libgtk-x11-2.0.so.0 (0x00007f61a731e000)&lt;br /&gt; libpolkit.so.2 =&gt; /usr/lib64/libpolkit.so.2 (0x00007f61a7105000)&lt;br /&gt; libgdk-x11-2.0.so.0 =&gt; /usr/lib64/libgdk-x11-2.0.so.0 (0x00007f61a6e66000)&lt;br /&gt; libatk-1.0.so.0 =&gt; /usr/lib64/libatk-1.0.so.0 (0x00007f61a6c46000)&lt;br /&gt; libgio-2.0.so.0 =&gt; /lib64/libgio-2.0.so.0 (0x00007f61a69d2000)&lt;br /&gt; libpangoft2-1.0.so.0 =&gt; /usr/lib64/libpangoft2-1.0.so.0 (0x00007f61a67a4000)&lt;br /&gt; libgdk_pixbuf-2.0.so.0 =&gt; /usr/lib64/libgdk_pixbuf-2.0.so.0 (0x00007f61a6587000)&lt;br /&gt; libpangocairo-1.0.so.0 =&gt; /usr/lib64/libpangocairo-1.0.so.0 (0x00007f61a637c000)&lt;br /&gt; libcairo.so.2 =&gt; /usr/lib64/libcairo.so.2 (0x00007f61a6107000)&lt;br /&gt; libpango-1.0.so.0 =&gt; /usr/lib64/libpango-1.0.so.0 (0x00007f61a5ebe000)&lt;br /&gt; libfreetype.so.6 =&gt; /usr/lib64/libfreetype.so.6 (0x00007f61a5c25000)&lt;br /&gt; libfontconfig.so.1 =&gt; /usr/lib64/libfontconfig.so.1 (0x00007f61a59f3000)&lt;br /&gt; libgobject-2.0.so.0 =&gt; /lib64/libgobject-2.0.so.0 (0x00007f61a57b0000)&lt;br /&gt; libgmodule-2.0.so.0 =&gt; /lib64/libgmodule-2.0.so.0 (0x00007f61a55ad000)&lt;br /&gt; libglib-2.0.so.0 =&gt; /lib64/libglib-2.0.so.0 (0x00007f61a52cb000)&lt;br /&gt; libdbus-1.so.3 =&gt; /lib64/libdbus-1.so.3 (0x00007f61a508d000)&lt;br /&gt; libgweather.so.1 =&gt; /usr/lib64/libgweather.so.1 (0x00007f61a4e75000)&lt;br /&gt; libpthread.so.0 =&gt; /lib64/libpthread.so.0 (0x00007f61a4c58000)&lt;br /&gt; libc.so.6 =&gt; /lib64/libc.so.6 (0x00007f61a48e6000)&lt;br /&gt; libm.so.6 =&gt; /lib64/libm.so.6 (0x00007f61a4661000)&lt;br /&gt; libxcb-xlib.so.0 =&gt; /usr/lib64/libxcb-xlib.so.0 (0x00007f61a445f000)&lt;br /&gt; libxcb.so.1 =&gt; /usr/lib64/libxcb.so.1 (0x00007f61a4244000)&lt;br /&gt; libdl.so.2 =&gt; /lib64/libdl.so.2 (0x00007f61a403f000)&lt;br /&gt; libgnome-keyring.so.0 =&gt; /usr/lib64/libgnome-keyring.so.0 (0x00007f61a3e2d000)&lt;br /&gt; libuuid.so.1 =&gt; /lib64/libuuid.so.1 (0x00007f61a3c28000)&lt;br /&gt; libssl.so.7 =&gt; /lib64/libssl.so.7 (0x00007f61a39d9000)&lt;br /&gt; libcrypto.so.7 =&gt; /lib64/libcrypto.so.7 (0x00007f61a3675000)&lt;br /&gt; libz.so.1 =&gt; /lib64/libz.so.1 (0x00007f61a3460000)&lt;br /&gt; libavahi-glib.so.1 =&gt; /usr/lib64/libavahi-glib.so.1 (0x00007f61a325d000)&lt;br /&gt; libavahi-common.so.3 =&gt; /usr/lib64/libavahi-common.so.3 (0x00007f61a3050000)&lt;br /&gt; libavahi-client.so.3 =&gt; /usr/lib64/libavahi-client.so.3 (0x00007f61a2e40000)&lt;br /&gt; libresolv.so.2 =&gt; /lib64/libresolv.so.2 (0x00007f61a2c28000)&lt;br /&gt; libselinux.so.1 =&gt; /lib64/libselinux.so.1 (0x00007f61a2a0b000)&lt;br /&gt; libutil.so.1 =&gt; /lib64/libutil.so.1 (0x00007f61a2808000)&lt;br /&gt; libgailutil.so.18 =&gt; /usr/lib64/libgailutil.so.18 (0x00007f61a2601000)&lt;br /&gt; libsasl2.so.2 =&gt; /usr/lib64/libsasl2.so.2 (0x00007f61a23e6000)&lt;br /&gt; libcamel-1.2.so.14 =&gt; /usr/lib64/libcamel-1.2.so.14 (0x00007f61a216b000)&lt;br /&gt; libplds4.so =&gt; /lib64/libplds4.so (0x00007f61a1f67000)&lt;br /&gt; libplc4.so =&gt; /lib64/libplc4.so (0x00007f61a1d63000)&lt;br /&gt; libnspr4.so =&gt; /lib64/libnspr4.so (0x00007f61a1b26000)&lt;br /&gt; libgnutls.so.26 =&gt; /usr/lib64/libgnutls.so.26 (0x00007f61a187b000)&lt;br /&gt; libgcrypt.so.11 =&gt; /lib64/libgcrypt.so.11 (0x00007f61a1608000)&lt;br /&gt; libORBitCosNaming-2.so.0 =&gt; /usr/lib64/libORBitCosNaming-2.so.0 (0x00007f61a1401000)&lt;br /&gt; /lib64/ld-linux-x86-64.so.2 (0x0000000000110000)&lt;br /&gt; libgsf-1.so.114 =&gt; /usr/lib64/libgsf-1.so.114 (0x00007f61a11c3000)&lt;br /&gt; libcroco-0.6.so.3 =&gt; /usr/lib64/libcroco-0.6.so.3 (0x00007f61a0f87000)&lt;br /&gt; libpng12.so.0 =&gt; /usr/lib64/libpng12.so.0 (0x00007f61a0d61000)&lt;br /&gt; libnsl.so.1 =&gt; /lib64/libnsl.so.1 (0x00007f61a0b47000)&lt;br /&gt; libXcomposite.so.1 =&gt; /usr/lib64/libXcomposite.so.1 (0x00007f61a0944000)&lt;br /&gt; libXdamage.so.1 =&gt; /usr/lib64/libXdamage.so.1 (0x00007f61a0742000)&lt;br /&gt; libXfixes.so.3 =&gt; /usr/lib64/libXfixes.so.3 (0x00007f61a053c000)&lt;br /&gt; libexpat.so.1 =&gt; /lib64/libexpat.so.1 (0x00007f61a0313000)&lt;br /&gt; libXext.so.6 =&gt; /usr/lib64/libXext.so.6 (0x00007f61a0102000)&lt;br /&gt; libXrender.so.1 =&gt; /usr/lib64/libXrender.so.1 (0x00007f619fef8000)&lt;br /&gt; libXinerama.so.1 =&gt; /usr/lib64/libXinerama.so.1 (0x00007f619fcf6000)&lt;br /&gt; libXi.so.6 =&gt; /usr/lib64/libXi.so.6 (0x00007f619faed000)&lt;br /&gt; libXrandr.so.2 =&gt; /usr/lib64/libXrandr.so.2 (0x00007f619f8e5000)&lt;br /&gt; libXcursor.so.1 =&gt; /usr/lib64/libXcursor.so.1 (0x00007f619f6db000)&lt;br /&gt; libpixman-1.so.0 =&gt; /usr/lib64/libpixman-1.so.0 (0x00007f619f496000)&lt;br /&gt; libcap.so.2 =&gt; /lib64/libcap.so.2 (0x00007f619f292000)&lt;br /&gt; libXdmcp.so.6 =&gt; /usr/lib64/libXdmcp.so.6 (0x00007f619f08c000)&lt;br /&gt; libgssapi_krb5.so.2 =&gt; /usr/lib64/libgssapi_krb5.so.2 (0x00007f619ee5d000)&lt;br /&gt; libkrb5.so.3 =&gt; /usr/lib64/libkrb5.so.3 (0x00007f619ebbb000)&lt;br /&gt; libcom_err.so.2 =&gt; /lib64/libcom_err.so.2 (0x00007f619e9b7000)&lt;br /&gt; libk5crypto.so.3 =&gt; /usr/lib64/libk5crypto.so.3 (0x00007f619e792000)&lt;br /&gt; libcrypt.so.1 =&gt; /lib64/libcrypt.so.1 (0x00007f619e559000)&lt;br /&gt; libssl3.so =&gt; /lib64/libssl3.so (0x00007f619e327000)&lt;br /&gt; libsmime3.so =&gt; /lib64/libsmime3.so (0x00007f619e0fc000)&lt;br /&gt; libnss3.so =&gt; /lib64/libnss3.so (0x00007f619dda1000)&lt;br /&gt; libnssutil3.so =&gt; /lib64/libnssutil3.so (0x00007f619db84000)&lt;br /&gt; libsqlite3.so.0 =&gt; /usr/lib64/libsqlite3.so.0 (0x00007f619d91b000)&lt;br /&gt; libtasn1.so.3 =&gt; /usr/lib64/libtasn1.so.3 (0x00007f619d70a000)&lt;br /&gt; libgpg-error.so.0 =&gt; /lib64/libgpg-error.so.0 (0x00007f619d507000)&lt;br /&gt; libbz2.so.1 =&gt; /lib64/libbz2.so.1 (0x00007f619d2f6000)&lt;br /&gt; libkrb5support.so.0 =&gt; /usr/lib64/libkrb5support.so.0 (0x00007f619d0ec000)&lt;br /&gt; libkeyutils.so.1 =&gt; /lib64/libkeyutils.so.1 (0x00007f619cee9000)&lt;/pre&gt;&lt;br /&gt;I think that's insane. Is all of this really needed? As a random example, what is libcom_err.so? Oh, of course...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ rpm -q -f /lib64/libcom_err.so.2&lt;br /&gt;e2fsprogs-libs-1.41.3-2.fc10.x86_64&lt;br /&gt;&lt;br /&gt;$ yum search e2fsprogs-libs&lt;br /&gt;[...]&lt;br /&gt;e2fsprogs-libs.i386 : Ext2/3 filesystem-specific shared libraries and headers&lt;/pre&gt;&lt;br /&gt;So I wonder... is this why the memory usage of clock-applet blows up, does it really matter, and can we do anything about it?&lt;br /&gt;&lt;br /&gt;I have a feeling that this is yet another sign of how the GNU/Linux desktop is heading the wrong way. It smells a lot like &lt;span style="font-weight: bold;"&gt;bloat&lt;/span&gt; :-(&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Vegard&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-5568055895227065871?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/5568055895227065871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=5568055895227065871' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5568055895227065871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/5568055895227065871'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2009/01/bloat.html' title='Bloat'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-2704255322734177267</id><published>2008-11-11T20:39:00.007+01:00</published><updated>2008-11-11T22:00:45.669+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Recursive type definitions in C</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;It's been a while -- I've been mostly busy with university. Maybe I won't try to follow four classes next year. In other news, we didn't make it (with kmemcheck) for 2.6.28 either. Oh well. We did at least make an impression by discovering two more bugs in 2.6.28-rc.&lt;br /&gt;&lt;br /&gt;Now for the topic of this post: Recursive type definitions in C. More specifically, the types I want to write about are not structs, but function pointers. We may use typedefs to define types which refer to function pointers:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;typedef void (*funcpointer_t)();&lt;/pre&gt;&lt;br /&gt;Not strictly necessary to make it a new named type, but it helps readability. This is all well and good; we can declare variables that hold function pointers, declare functions that take function pointers as parameters, or even declare functions that return function pointers (to functions with this specific signature):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;funcpointer_t x;&lt;br /&gt;&lt;br /&gt;void do_a(funcpointer_t f);&lt;br /&gt;&lt;br /&gt;funcpointer_t do_b(void);&lt;/pre&gt;&lt;br /&gt;Now, what I really wanted to do was to create a parser in C where a variable would hold the next function to call, and where the function itself returned a (function) pointer to the next function to call (i.e. the next state of the parser). It would look something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;funcpointer_t init_state(const char *token) {&lt;br /&gt;   /* ... */&lt;br /&gt;   return &amp;amp;some_other_state;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;funcpointer_t some_other_state(const char *token) {&lt;br /&gt;   /* ... */&lt;br /&gt;   return &amp;amp;some_other_state;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void parse() {&lt;br /&gt;   funcpointer_t state = &amp;amp;init_state;&lt;br /&gt;&lt;br /&gt;   while (token = read_token())&lt;br /&gt;       state = state(token);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Okay, so this looks quite good. But how do we define funcpointer_t? Defining structs that have pointers of the same type is quite easy, since the compiler already knows about the type as soon as you start defining it. The most obvious example is the linked list:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;struct list_node {&lt;br /&gt;   struct list_node *next;&lt;br /&gt;   /* ... */&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;Another possibility includes forward declarations, where we simply declare that a type exists, without defining it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;struct a;&lt;br /&gt;struct b {&lt;br /&gt;   struct a *x;&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;The same goes for functions. They can refer to themselves, since we must provide their name at the start of their definition, or declare them beforehand. But how can we do this with function pointers?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Vegard&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-2704255322734177267?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/2704255322734177267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=2704255322734177267' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2704255322734177267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/2704255322734177267'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/11/recursive-type-definitions-in-c.html' title='Recursive type definitions in C'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-6559413985851255959</id><published>2008-09-16T21:26:00.002+02:00</published><updated>2008-09-16T22:19:34.883+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>"Scribe" and cross-compiling for Windows</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;First of all: Scribe. That is my new pet project. Actually, I don't know how serious it is yet. But I've made a Project out of it; maybe somebody else who is interested will come along and help. We'll see.&lt;br /&gt;&lt;br /&gt;But what is it? Well, it's really just a demo so far. A demo of a "3D pixel engine". It started out as an experiment to see how the graphics from "The Legend of Zelda: Link's awakening" would look in 3D. So I took the Link sprites and some desert tiles and wrote a C++ program that used OpenGL to render it in perspective. And it looked quite good. Well, I must admit that I'm a huge fan of pixel art. It's just so incredible how much spirit and soul you can put into a 16x16 bitmap! And most 3D games out there use high-resolution textures with bilinear filtering and who knows what else to try to make it look halfway realistic...&lt;br /&gt;&lt;br /&gt;I actually wrote this code around the end of October 2007 (just before I started working on kmemcheck), and it's been lying in my "programming" folder ever since. I recovered it the other day and thought that I should publish it as an open source/free software program, simply because I have no reason not to. I probably won't have that much time to develop this further, but maybe somebody else will find it interesting and pick it up. It's open source, these things do happen!&lt;br /&gt;&lt;br /&gt;There was one major hitch, though. I can't distribute the Zelda graphics. And copyright law has to be upheld! (As an open source/free software programmer, what other position can I take?)&lt;br /&gt;&lt;br /&gt;I decided to look around the net for some free graphics, and free graphics I found! In particular, I found &lt;span style="text-decoration: underline;"&gt;bubble league&lt;/span&gt;, the website of Alan Trullinger. Apparently he had planned to make some RPG game and had spent a summer making the graphics for it. Apparently, the game was also never released, so he gave away all the graphics for free (distributed under the Creative Commons license). This is how my program looks using his files:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://github.com/vegard/scribe/tree/master%2Fpng%2Fscribe.png?raw=true"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://github.com/vegard/scribe/tree/master%2Fpng%2Fscribe.png?raw=true" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;That's not too bad, is it? The little guy can walk around and jump. (The animation is an incredible piece of work, with 8 frames worth of animation in each direction!)&lt;br /&gt;&lt;br /&gt;(Of course, nothing beats the Zelda graphics, but that's a different story.)&lt;br /&gt;&lt;br /&gt;Are you interested in trying it out? Perhaps you are even interested in contributing something to it? In either case, I've created a git repository for the project at &lt;a href="http://github.com/vegard/scribe/"&gt;http://github.com/vegard/scribe/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(Side note: GitHub is a really nice place. I haven't used it that much yet, but everything there is easy and pleasant and just works. It's really worth trying out if you're looking for git hosting. End of note.)&lt;br /&gt;&lt;br /&gt;All right. On to the second part of this post: Cross-compiling programs for Windows on Linux. Did you ever try to build MinGW on Linux, only to discover after hours of compiling the compiler, that it doesn't really work? (I don't remember exactly what went wrong, maybe it was missing Windows headers, or missing Windows libraries, or something. I must have suppressed the memories.) Well, there is a solution to that problem too.&lt;br /&gt;&lt;br /&gt;Use Wine! I installed Dev-C++ on my Fedora Linux using Wine. Then I created a project inside Dev-C++, imported my source code, installed a few &lt;a href="http://devpaks.org/"&gt;Devpaks&lt;/a&gt;, and... it worked. A slight (but only slight) elaboration of this process can be found in the &lt;a href="http://github.com/vegard/scribe/tree/master/INSTALL.win32"&gt;Win32 build instructions&lt;/a&gt; for "Scribe".&lt;br /&gt;&lt;br /&gt;The only problem I had was that the program wouldn't link unless the linker directives were put in the right order. But that's shame on me for being spoiled with shared libraries (I built with -static to avoid DLL hell).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-6559413985851255959?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/6559413985851255959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=6559413985851255959' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6559413985851255959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6559413985851255959'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/09/scribe-and-cross-compiling-for-windows.html' title='&quot;Scribe&quot; and cross-compiling for Windows'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-4630063522160300588</id><published>2008-08-29T22:00:00.005+02:00</published><updated>2008-09-09T19:19:28.849+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kmemcheck'/><title type='text'>REP STOS -- part 2</title><content type='html'>I finally did it.&lt;br /&gt;&lt;br /&gt;I fixed the problem with single-stepping REP STOS (and MOVS) instructions on the P4. (Look in the blog archive to find the original post.)&lt;br /&gt;&lt;br /&gt;At first, I wanted emulate the instructions completely. But it wasn't really that easy. My naïve implementation &lt;span style="font-weight: bold;"&gt;did&lt;/span&gt; support different register/data widths. But I soon hit some real show-stoppers. It turned out that the kernel will use REP STOS or MOVS on strings which may not be aligned naturally. This means that memory accesses may now cross a page boundary, which is a big problem. Now we suddenly have to look for page boundaries, and in the case of REP MOVS, we must watch out for both the ESI and EDI registers.&lt;br /&gt;&lt;br /&gt;The reason is of course that pages are tracked one by one, and if we cross over to a new page, we have to make sure that it is also marked present (P flag) in the page tables before touching it. Two consecutive pages are also not guaranteed to have consecutive shadow-memory pages (in fact, that's very unlikely), so we should also take care of changing shadow-memory pointers upon hitting a page boundary. But still, that is not so easy when we have a single write that can cross the boundary.&lt;br /&gt;&lt;br /&gt;I thought about this for a long while and I came up with a scheme that would work: We can allow a REP MOVS/STOS run to cross at most one page boundary. Then we only need to keep track of at most two pages at the same time (or four pages for REP MOVS), and if we hit this limit, then we can return to the code and simply wait for a new page fault to restart where we left off.&lt;br /&gt;&lt;br /&gt;But still it was not quite that easy. Emulating the memory accesses in effect means that we do them from the page fault handler. The kernel got through the boot sequence and a bit into userspace. But then it would BUG on a test that wanted irqs to be enabled. After a bit of debugging, I found (to my great horror) that copy_to_user() was using REP MOVS to move data from the kernel into userspace. This is of course not safe, when we consider that the userspace page might not even be present in the page tables. Because now we were making a write from the kernel (in fact, from the page fault handler itself) to userspace, causing a new page fault, and then calling into various memory subsystem functions to allocate a new page for userspace. All of this with interrupts disabled, which is forbidden. (I believe that this is also the reason why copy_to_user() cannot be used in atomic contexts. Who can confirm?)&lt;br /&gt;&lt;br /&gt;We absolutely cannot emulate the instruction by doing the write from the page fault handler. So what can we do?&lt;br /&gt;&lt;br /&gt;Well, all is not lost. I am rather proud of my little hack, too. This is what I wrote (in my great excitement) to Ingo Molnar:&lt;br /&gt;&lt;blockquote&gt;Instead of emulating the _whole_ REP MOVS/STOS, we only emulate the REP part. That is, on #PF, we increment %eip by one, which means that when the #PF returns, it will execute just a normal MOVS/STOS instruction (and give is the #DB straight afterwards). Now, in the #DB, we check the flag that says "was this really a REP instruction?" and if it was, we start counting down %ecx and rewinding %eip each time until %ecx is 0. Each time we return to the original instruction and let the CPU execute it natively. When %ecx is 0, we turn off single-stepping and hide the pages again.&lt;/blockquote&gt;The great thing is that it actually works. With this (rather small) patch, I am able to boot my P4 and get exactly the same error reports that I get on my Pentium Dual-Core laptop.&lt;br /&gt;&lt;br /&gt;This also prompted me to start fixing the numerous false positive warnings that occur because kmemcheck is reporting eagerly. Most prominent of these are the bitfield operations, which load a multiple of 8 bits at a time, even though just one of the bits are actually used. The solution is to explicitly initialize the whole bitfield at once just after the struct has been allocated. Yes, this means that we won't be able to detect errors in the use of uninitialized bitfields, but this has always been true and is a result of the combination of the x86 architecture and the way we detect memory accesses.&lt;br /&gt;&lt;br /&gt;And this is the current status: 0 errors reported during kernel initialization, 3 errors reported during userspace initialization, 0 errors while transferring a 4 MiB bzImage over SSH. Compare that to the ~2400 errors this would give us a month ago. This time I believe that we are truly ready for mainline. It will be interesting to see if anybody will try it out or review the patches, however...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-4630063522160300588?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/4630063522160300588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=4630063522160300588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/4630063522160300588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/4630063522160300588'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/08/rep-stos-part-2.html' title='REP STOS -- part 2'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-4977775624031463065</id><published>2008-07-25T16:24:00.014+02:00</published><updated>2008-07-28T13:27:31.617+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Notes on source code preprocessing</title><content type='html'>&lt;span style="font-style: italic;"&gt;(This post contains some reflections on the hypothetical design of an ideal programming language...)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don't use or support the use of preprocessing source code. Preprocessing means that all the tools which operate on the source code (including editors, compilers, static analyzers, etc.) will necessarily need to either support preprocessing themselves, or call the preprocessor before operating on the resultant source code.&lt;br /&gt;&lt;br /&gt;Consider, for example, a simple tool that parses C code and searches for a given text in all the literal strings found in that code. If the source code needs to be preprocessed, then certain parts of the code may not be searched if the part in question is contained within the equivalent of a C-preprocessor &lt;span style="font-style: italic;"&gt;#ifdef&lt;/span&gt;/&lt;span style="font-style: italic;"&gt;#endif&lt;/span&gt; block. On the other hand, if we want our tool to also find strings inside these sections, then we can no longer use a C parser because &lt;span style="font-style: italic;"&gt;#ifdef&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;#endif&lt;/span&gt; are not recognized by the C parser proper.&lt;br /&gt;&lt;br /&gt;(The solution to the problem might include using regular expressions as a kind of heuristic to determine where the strings are, and then do concatenations, etc. However, this is only an approximate solution, and is in general not entirely satisfying. What about the more complex task of looking for specific variable or function declarations? In fact, a number of such tools have had to deal with variations of this problem; see for example &lt;a href="http://lxr.linux.no/"&gt;LXR&lt;/a&gt; and &lt;a href="http://www.emn.fr/x-info/coccinelle/"&gt;Coccinelle&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Multiple, different types of preprocessors also don't mix very well. For example, as an extension to many programming languages, the source code is preprocessed so that SQL queries are substituted with the (possibly verbose) support code which would otherwise be needed to prepare and execute the query in question. Now we have exactly the same problem as mentioned above, which is that support tools (editors, compilers, etc.) will have to either support the preprocessor language or (more likely) always operate on already-preprocessed source code, with all the aforementioned drawbacks. In some cases, the order of preprocessing will also become significant, or different preprocessor languages might be incompatible.&lt;br /&gt;&lt;br /&gt;Another practical aspect of preprocessing is that the code which is inside such &lt;span style="font-style: italic;"&gt;#ifdef&lt;/span&gt; blocks will be compiled only conditionally; the compiler might not even look at it. This means that the compiler is a lot less useful than it could be. It is one of the main tasks of the compiler to inform the programmer when he/she is writing something which is internally inconsistent, such as calling a function with the wrong argument types. (This is entirely possible if there is a caller of the function inside an &lt;span style="font-style: italic;"&gt;#ifdef&lt;/span&gt; block and the definition of the function was later changed to take different arguments.)&lt;br /&gt;&lt;br /&gt;In conclusion, I think C/C++ could have done a lot better in this area. On the other hand, a lot of other programming languages &lt;span style="font-style: italic;"&gt;did&lt;/span&gt; get it right. But maybe the need for alternative compilation is greater in the lower-level languages and it's really just a trade-off between performance and usability.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-4977775624031463065?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/4977775624031463065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=4977775624031463065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/4977775624031463065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/4977775624031463065'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/07/notes-on-source-code-preprocessing.html' title='Notes on source code preprocessing'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-1068279455506974187</id><published>2008-07-21T10:17:00.004+02:00</published><updated>2008-07-22T00:13:44.034+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kmemcheck'/><title type='text'>Single-stepping a REP STOS...</title><content type='html'>I've recently made a startling discovery that explains a &lt;span style="font-weight: bold;"&gt;LOT&lt;/span&gt; about how kmemcheck has been working (or not) on one of my machines.&lt;br /&gt;&lt;br /&gt;Yesterday I added the kmemcheck hooks into the DMA API, which means that we should now not give any false-positive errors about DMA-able memory. The patch was essentially a one-liner, since the rest of the DMA API deals with whole pages only (and they come straight from the page allocator, so they're not tracked anyway).&lt;br /&gt;&lt;br /&gt;But still I was getting a huge amount of errors from sysfs code. This puzzled me for many hours. The code was apparently okay. In fact, the allocation in question was explicitly being zeroed out (it was calling kzalloc()), so it shouldn't have been possible to even find any use of uninitialized memory in it. I added some code to dump the memory along with the shadow dump, and it showed that the array was indeed being zeroed, but not marked initialized.&lt;br /&gt;&lt;br /&gt;Because memset() is such a common operation (and needs to be fast), I've written a custom memset() function that checks whether the target memory is being tracked or not; if it is, we don't have to take any page fault at all, but we can simply zero the memory and set the initialization status to "initialized" at the same time.&lt;br /&gt;&lt;br /&gt;I suspected my custom memset() of being in error. So I commented it out. And the result was even more startling; I now got a kmemcheck error on just about every memory access...&lt;br /&gt;&lt;br /&gt;Something had to be wrong with the built-in memset. This is its definition:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;static inline void * __memset_generic(void * s, char c,size_t count)&lt;br /&gt;{&lt;br /&gt;     int d0, d1;&lt;br /&gt;     __asm__ __volatile__(&lt;br /&gt;             "rep\n\t"&lt;br /&gt;             "stosb"&lt;br /&gt;             : "=&amp;amp;c" (d0), "=&amp;amp;D" (d1)&lt;br /&gt;             :"a" (c),"1" (s),"0" (count)&lt;br /&gt;             :"memory");&lt;br /&gt;     return s;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(Source code taken from the Linux Kernel. This code is licensed under the GNU GPL version 2.)&lt;br /&gt;&lt;br /&gt;Taking a new look at the first kmemcheck error reported, I got another clue. The kzalloc() allocation was uninitialized except for the very first byte!&lt;br /&gt;&lt;br /&gt;I wrote a short program for userspace which called the above function and single-stepped it with gdb on my two machines, one P4 3.0 GHz, and one Pentium Dual-Core 1.47 GHz. To my great surprise, the P4 skipped the whole REP STOS construct in one go, while the Dual-Core got a trap for each repetition of the STOS.&lt;br /&gt;&lt;br /&gt;This is very grave news for kmemcheck. I had tested it on my Dual-Core earlier and thought that it would behave the same for all CPUs; there's not a word about single-stepping REP instructions in the Intel's System Development Manuals that I could find, anyway.&lt;br /&gt;&lt;br /&gt;There are basically two solutions to the problem:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Black-list the models that don't single-step each repetition&lt;/li&gt;&lt;li&gt;Emulate the instruction (i.e. no single-stepping at all for the REP instructions)&lt;/li&gt;&lt;/ol&gt;And neither of them is particularly attractive.&lt;br /&gt;&lt;br /&gt;But I have started working on instruction emulation to see how far I can get.&lt;br /&gt;&lt;br /&gt;I've also contacted Intel and asked for more information about the peculiarity.&lt;br /&gt;&lt;br /&gt;I only hope that there are not more unpleasant surprises like this...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Vegard&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PS&lt;/span&gt;: I have written a (32-bit) userspace &lt;a href="http://folk.uio.no/vegardno/repstos.c"&gt;program&lt;/a&gt; that backs up my suspicions. Compare these outputs:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ ./a.out&lt;br /&gt;processor       : 7&lt;br /&gt;cpu family      : 6&lt;br /&gt;model           : 15&lt;br /&gt;model name      : Intel(R) Xeon(R) CPU           E5320  @ 1.86GHz&lt;br /&gt;&lt;br /&gt;Counted 1000 REP STOS instructions (expected 1000).&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;$ ./a.out&lt;br /&gt;processor       : 1&lt;br /&gt;cpu family      : 15&lt;br /&gt;model           : 6&lt;br /&gt;model name      : Intel(R) Pentium(R) 4 CPU 3.00GHz&lt;br /&gt;&lt;br /&gt;Counted 55 REP STOS instructions (expected 1000).&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-1068279455506974187?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/1068279455506974187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=1068279455506974187' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1068279455506974187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/1068279455506974187'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/07/single-stepping-rep-stos.html' title='Single-stepping a REP STOS...'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3663284046896592766.post-6698865505075946933</id><published>2008-07-14T10:10:00.001+02:00</published><updated>2008-07-21T11:09:03.348+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fedora'/><title type='text'>Fedora 8 -&gt; 9 upgrade</title><content type='html'>Yesterday, I decided that it was time to try out Fedora 9; after all, it's been a few months since it was released, and having just made a backup, I found that this was a convenient time to perform the upgrade.&lt;br /&gt;&lt;br /&gt;Things did not start out so well, though. The installer seemed incredibly slow this time. There is a progress bar which shows how many packages that have been installed, but this could probably have been dropped; the next phase of installation, which I believe is the configuration of the just-installed packages, seemed to take just as long as the installation itself, and that with no progress bar at all (though, admittedly, with a rather honest "This may take a long time").&lt;br /&gt;&lt;br /&gt;Well, the installer eventually completed and I rebooted the system. GRUB loaded as usual, except for the new spiffy background image. I picked the most recent kernel in the list, 2.6.25.9-40.fc8, even though the 'fc8' suffix puzzled me somewhat, but no, it didn't boot. Apparently the kernel (or initrd?) was unable to find my LVM volumes, and so couldn't mount my root partition. Well, at least the old kernel, 2.6.25.6-27.fc8, was still present in the menu, and choosing this the next time got me all the way to the (now even spiffier) graphical login screen.&lt;br /&gt;&lt;br /&gt;My desktop shows up as usual and things seem fine. I decide to grab the most recent updates from the web, as I had downloaded the release DVD which contains packages which are now almost two months old. Unfortunately, all that 'yum' can do for me is to print a message about a missing _sha256 python package and some download instructions. I search the web for the exact error message, and I find a forum where others have the same problem [1]. The suggestion there is to download the RPMs that I need and install them manually using the 'rpm' tool, which I do. This method did in fact work, but only after resolving a few dependencies by hand and downloading amongst other things the updated python and yum packages.&lt;br /&gt;&lt;br /&gt;And now that yum again runs successfully, I turn to those updates I've been waiting for. In the world of Free Software, changes happen quickly and the Fedora packages are usually updated quite frequently. However, all I see is a list of just two lone packages which both belong to the ".fc8" set of packages. Did the upgrade somehow forget to switch my package repositories?&lt;br /&gt;&lt;br /&gt;No, that question will have to remain unanswered. I do not know the internals of yum, nor do I have any wish to do so (beyond fixing my broken system, obviously). I don't want to spend time on fixing the package manager; that's why I use one to begin with!&lt;br /&gt;&lt;br /&gt;For the record, though my opinions might be biased by the experiences just recounted, I am also unimpressed by the new Firefox 3. I feel that the new user interface has been forced upon me, and it would be better to leave the former theme as it was and instead allow the user to choose the new one, if so he or she dares. I simply don't like the way things look; the elements of the drop-down URL list/chooser now displays titles of the webpages in addition to the URL itself, an incredibly annoying misfeature when my habits are already tuned to one specific behaviour. I can now also report that Firefox, only showing my Gmail inbox, now defaults to using 10% CPU when idle instead of the usual 3% of Firefox 2.5.&lt;br /&gt;&lt;br /&gt;So thank you, but no thanks. I should have stayed with F8.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Vegard&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1: &lt;a href="http://www.fedoraforum.org/forum/showthread.php?t=193507"&gt;http://www.fedoraforum.org/forum/showthread.php?t=193507&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PS&lt;/span&gt;: When attempting to start gvim (to copy this very text into my browser), I got the following error: "gvim: error while loading shared libraries: libperl.so: cannot open shared object file: No such file or directory".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PPS&lt;/span&gt;: Several other programs were broken as well, including git, which made the computer completely useless for me. In the end, I installed F9 from scratch and restored my home directory. Yum has been downloading/installing updates for an hour now. Still, Tomboy Notes crashed while Yum was installing a SELinux policy update.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3663284046896592766-6698865505075946933?l=vegardno.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vegardno.blogspot.com/feeds/6698865505075946933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3663284046896592766&amp;postID=6698865505075946933' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6698865505075946933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3663284046896592766/posts/default/6698865505075946933'/><link rel='alternate' type='text/html' href='http://vegardno.blogspot.com/2008/07/fedora-8-9-upgrade.html' title='Fedora 8 -&gt; 9 upgrade'/><author><name>Vegard</name><uri>http://www.blogger.com/profile/04821963505711884515</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
