Archive for the 'System in General' Category

26 DecCompiling A Really Good Kernel

As most very experienced Linux users know, a custom-compiled kernel is a very good thing if done well. Your performance can double sometimes, because you are setting up a kernel optimized for your CPU.  But it can be difficult to get it right. There are a number of different ways to do it, and every major distro has a distro-specific way. Here is a distro-irrelevant process I use to build my running kernel.  I prefer this, because sometimes distro-specific kernel tools do not work as expected and/or documented.

This procedure includes the Real-Time Linux additions, and other configurations which are very good to keep latency — the time between MIDI controller keyhit and MIDI synth output — as low as possible, while keeping overall horsepower as high as possible. 10ms of latency (as reported by jackd) can be a liability when playing live; 5ms is often OK. With 2GHz-plus multicore hardware and 2G RAM, plus a realtime kernel, plus a good $100 sound card, you’ll be good to between one and three ms, which is not humanly detectable.

Much of this is in root-permissions command shell; and if you delete anything you shouldn’t, it can be dangerous to your system :-)  You have been warned :-) :-)

Our first step, is to prepare a compilation environment.  We’ll stay in normal user command shell for now, change to the user home directory, create a directory for compilation, and get the source code for the new kernel.  Here are commands:

cd ~ mkdir kernel
cd kernel
wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.6.tar.bz2
wget http://www.kernel.org/pub/linux/kernel/projects/rt/patch-2.6.31.6-rt19.bz2

We also need the source for the kernel we are running right now.  This depends on the distro.  On Debian, I used the default GUI packager (Synaptic), and I retrieved package “linux-source” according to the version I found using the command:

uname -a

showed me I was using kernel 2.6.30-2 provided by Debian; I therefore installed package linux-source-2.6.30.

The next step is to go back to the above user-level command line shell, make sure we’re still in the right directory, unpack the source code package, and add the rtlinux additions:

cd ~/kernel
tar xf linux-2.6.31.6
cd linux-2.6.31.6
bzip2 -cd ../patch-2.6.31.6-rt19.bz2 | patch -p1

Now we add the tools we need to compile a kernel, to the machine.  There are quite a few bits needed, and I don’t know the simplest way to do it under anything not Debian-based.  But under Debian, Ubuntu, or relatives, this works straightforwardly, in a root command shell; it uses the command-line packaging tools to get everything needed (the deps, dependencies) for building the currently running kernel.  You may need to put the version number on the end.

apt-get build-dep linux-image

Now we configure the source code, to set it up to build the special kernel we want.  The kernel builder looks at config file ‘.config’ (with dot first), so we’ll make that file, tell the builder to look at it, and then build and start the configurator.  We’re back in the user-level command shell:

make menuconfig

The above gets us into the full-screen kernel source configurator.  There are several things we need to add and change.  First we’ll go into the “General Setup” section:

  • Make an add-on name for your new kernel.  This is very important, because if we don’t do it, we risk overwriting the current kernel.  We very much want to keep the current kernel available, as a fallback.  It’s in the “General Setup”, in the “Local version” area second from the top.  The word “custom” is perfectly fine.  It will be added to the end of the default name.  No spaces or strange characters please!, because all sorts of Linux system functions will be reading this.
  • By default, the kernel is optimized for size.  This is quite helpful, unless you’re running lots and lots of RAM (for example, 4G RAM as in my case).  Then we want the compiler to optimize for speed and not worry about size.  This option is near the bottom of the list.
  • Turn profiling off.  Profiling can hurt performance, it’s used by kernel developers.

Now hit Esc and Esc again, to get back to the main menu.  We’ll choose CPU now, under “Processor type and features”.

  • Turn off “Tickless System (Dynamic Ticks)”.
  • Turn on “High Resolution Timer Support”.
  • Move down to “Processor Family”, and open it up.  Choose the processor which is closest to yours.  This can get tricky, especially on 32-bit systems where there are lots of options to cover the entire range from 386 all the way through the last of the 32-bit Intel Xeon server CPUs.  You’ll want to know your CPU, whether it’s Intel or AMD, whether it has 3DNow, sse, or sse2 support, et cetera.  If you get this right-on, you’ll get more horsepower than you dreamed was in your machine; if you undershoot, you’ll lose performance; if you overshoot too much, you will have built a perfectly good kernel which won’t run on your machine at all :-)  So choose VERY carefully here.   Your best first clue comes by running this command:
cat /var/log/messages | grep CPU0

which on my system yields four lines reading:

Dec 25 23:04:44 jebslinux kernel: [    0.014874] CPU0: AMD Phenom(tm) 9950 Quad-Core Processor stepping 03

As you will see, this is a good clue — but especially on 32-bit platforms there will still be some homework to do, to figure out how your CPU matches up to the kernel’s options.

  • Now hit Esc Esc again to go up one level, and move down to “Preemption Mode”.  Enter that section, and choose “Complete Preemption (Real-Time)”.  Then Esc Esc to go up again.
  • Move down fairly far, until you find “Timer frequency”.  Make sure this one is set to 1000 Hz.  Then Esc Esc to go up.
  • Move down to “Device Drivers”, and go in.  Move all the way to the second-to-last, “Staging Drivers”, and uncheck.  Staging drivers are experimental, beta, even alpha; we don’t want them at all, they can destabilize things.  Esc Esc.
  • Just one more.  We’ll speed up the system, by turning off some debugging code we don’t need.  Move down to “Kernel Hacking”, and go in.  Move pretty far down, to “Tracers”, and uncheck.  This takes care of a lot.

Now we’re ready to build!  Run these commands one at a time.  They will both take a while.  If you see “fatal error” at the end of either, you have done something sufficiently wrong, that it didn’t work :-)  This part is still for the user-level comand shell.

make bzImage
make modules

And now we’re ready for installation.  We’re now in root-level shell.  First steps are straightforward:

make modules_install
make install

Depending on the distro, the next step may be optional.  Let’s find out like this:

ls /boot/initr*

If there is anything listed, and nothing there matches your new kernel’s name, we need to create an initrd, also called an initramfs. As of kernel 2.6.33.1 built on RedHat 12+CCRMA, this was automatic; as of Debian Testing recent, I had to make one!  This is a big file which the kernel uses during boot, containing basic hardware information needed during the boot process.  If you have something like this, you may need to install the package for the application which can build you a new one:

apt-get install mkinitrd

To create an initrd, the first step is to move (in root command-shell) to /boot, where the kernels are stored, and look at the kernel file installed by ‘make install’ just previously.  In my case, my kernel file is “vmlinuz-2.6.31.6-rt19custom4″, because the add-on name I set was “custom4″.  Knowing you will have to replace “custom4″ with the add-on name you chose, here are the next steps:

cd /boot
update-initramfs -c -k 2.6.31.6-rt19custom4

We have just one big step left:  adding the new kernel (and initrd if it exists) to the boot loader.  There are three boot loaders in common use today:  grub, grub legacy, and LILO.  At this writing (12/26/2009), I believe that the majority of current distributions are still using so-called “grub legacy”; one thing for which I am grateful in Debian Testing, is that it uses the current grub.  I will cover grub and grub legacy below; in my own experience LILO has failed inexplicably often enough that I won’t recommend it.

If you are running grub and not grub legacy, the following command will work from a root-level command shell:

ls /boot/grub/grub.cfg

You will need to edit this file. Be very careful; if this file is bad enough, your system will reboot into a crash next time, you’ll have to rescue your system by reinstalling grub from a LiveCD, which can get sticky.

In grub.cfg, the areas of greatest importance to us will look much like this:

menuentry "Debian GNU/Linux, with Linux 2.6.30-2-amd64" {
insmod jfs
set root=(hd0,1)
search --no-floppy --fs-uuid --set 91694db0-2061-498d-9ada-09e767954bae
linux	/boot/vmlinuz-2.6.30-2-amd64 root=UUID=91694db0-2061-498d-9ada-09e767954bae ro  quiet
initrd	/boot/initrd.img-2.6.30-2-amd64
}
menuentry "Debian GNU/Linux, with Linux 2.6.30-2-amd64 (recovery mode)" {
insmod jfs
set root=(hd0,1)
search --no-floppy --fs-uuid --set 91694db0-2061-498d-9ada-09e767954bae
linux	/boot/vmlinuz-2.6.30-2-amd64 root=UUID=91694db0-2061-498d-9ada-09e767954bae ro single
initrd	/boot/initrd.img-2.6.30-2-amd64
}

For every kernel you have installed, there will be at least one of those curly-bracket sets, and possibly two; the second one on my system (from which the above came) is a single-user-mode boot option, like a safe mode boot for emergency fixes.  In my grub.cfg, near the top, I also have a line:

set default=0

This means that the first (#0) curly-bracket “menuentry” specification, will be automatically engaged by default.  There is also:

set timeout=5

which sets how long in seconds grub should pause, to permit you to choose the kernel you will boot.  Regardless of these two, you will want to duplicate the menuentry in use, making sure to replace both the vmlinuz and initrd filenames with the new ones.  It is best to place the new menu entries in the bottom of the list if your automatic setting is for the first; your first kernel very well may not work perfectly :-)  hint,  hint.  You can always edit your grub.cfg after you prove that your new kernel is good to go.

If you have grub legacy, you won’t have a grub.cfg; you will have a /boot/grub/menu.lst or occasionally a /boot/menu.lst:

ls /boot/grub/menu.lst
ls /boot/menu.lst

In menu.lst, the areas of greatest importance to us will look much like this:

title	Debian GNU/Linux, kernel 2.6.30.1-avlinux-lowlatency-pae
root	(hd0,0)
kernel	/boot/vmlinuz-2.6.30.1-avlinux-lowlatency-pae root=UUID=6ebe6c59-a06a-458f-8f33-8f2a2124865e ro
initrd	/boot/initrd.img-2.6.30.1-avlinux-lowlatency-pae
title	Debian GNU/Linux, kernel 2.6.30.1-avlinux-lowlatency-pae (single-user mode)
root	(hd0,0)
kernel	/boot/vmlinuz-2.6.30.1-avlinux-lowlatency-pae root=UUID=6ebe6c59-a06a-458f-8f33-8f2a2124865e ro single
initrd	/boot/initrd.img-2.6.30.1-avlinux-lowlatency-pae

For every kernel you have installed, there will be at least one of the “title” items a la the above, and possibly two; the second one on my old AVLinux system (from which the above came) is a single-user-mode boot option, like a safe mode boot for emergency fixes.  There are some hacks out there automating the creation of menu.lst files; these often use comment lines like “### BEGIN AUTOMAGIC KERNELS LIST” and “### END DEBIAN AUTOMAGIC KERNELS LIST” to surround automatically installed kernels.  You will need to duplicate your existing title items, replacing default kernel and initrd filenames with your new ones; and you should put the new ones outside of any automatic lists.  There are also lines like this:

default 0

which specify which “title” item to run automatically, and also

timeout	5

which specifies how long in seconds to wait until the automatic choice is started.

There are bells and whistles in both grub legacy and grub; some of these can cause the list to be hidden behind images, etc., and it is possible to turn off that timeout altogether so there is no choice.  I definitely recommend that you keep the timeout set to at least 3 seconds, and make sure no graphics hide the boot options from you.

And after you have edited your grub.cfg or menu.lst, you are ready to try a reboot.  Be brave!  If it works perfectly, you’re done.  If not, reboot into your original kernel, and try, try again.

08 DecFull-function Repo Set for Debian Testing

When one uses Debian Testing for high-test multimedia purposes, one must add repos.  Here is my current /etc/apt/sources.list :

deb http://ftp.gtlib.gatech.edu/debian/ squeeze main contrib
deb-src http://ftp.gtlib.gatech.edu/debian/ squeeze main contrib

deb http://security.debian.org/ squeeze/updates main contrib non-free
deb-src http://security.debian.org/ squeeze/updates main contrib non-free

deb http://ftp.gtlib.gatech.edu/debian/ sid main contrib
deb-src http://ftp.gtlib.gatech.edu/debian/ sid main contrib

deb http://ftp.gtlib.gatech.edu/debian/ experimental main contrib
deb-src http://ftp.gtlib.gatech.edu/debian/ experimental main contrib

#DEBIAN MULTIMEDIA
deb http://www.debian-multimedia.org/ squeeze main
deb-src http://www.debian-multimedia.org/ squeeze main
deb http://www.debian-multimedia.org/ sid main
deb-src ftp://ftp.debian-multimedia.org/ sid main
deb ftp://ftp.debian-multimedia.org/ experimental main

# Google
deb http://dl.google.com/linux/deb/ testing non-free main

# sidux sources added by smxi
deb http://ftp-mirror.internap.com/pub/sidux/debian/ sid main contrib non-free firmware fix.contrib fix.non-free
deb http://sidux.com/debian/ sid main contrib non-free firmware fix.contrib fix.non-free
deb-src http://sidux.com/debian/ sid main fix.main contrib non-free firmware fix.contrib fix.non-free

# Rivendell.  Some good and interesting code here.
deb http://debian.tryphon.org/ testing main contrib
deb-src http://debian.tryphon.org/ testing main contrib
deb http://debian.tryphon.org/ unstable main contrib
deb-src http://debian.tryphon.org/ unstable main contrib

# the Ubuntu Mozilla PPA.  Great for the current Thunderbird.
# Haven't tried it for Firefox yet, icebird is working just fine
# for me.
deb http://ppa.launchpad.net/ubuntu-mozilla-daily/ppa/ubuntu/ karmic main

03 DecDebian scripts for system upkeep

Some very interesting, useful, and functional command-line scripts are here:

http://smxi.org/site/about.htm

02 DecVideo Problems in Kernel Changes

I’m not yet sure how this works with ATI video, but if you’re running the nVidia-provided video drivers, you’ll need to remove them (sgfxi -n) before switching kernels and then reinstall them afterwards, or else X won’t know what to do.

02 NovCauses of ALSA Confusion

Sometimes, as many have noticed, sound will work well for a while — several minutes, several hours — and then latency will rise a lot, or static will overlay, or sound will stutter or stop altogether, or all of the above. I have taken to calling this phenomenon “ALSA confusion”, as in “ALSA becoming confused” about what it should be doing and how it should be doing it. I have thus far identified the following causes and cures for ALSA confusion:

  1. The ALSA Jack plugin.  Don’t try to use it.  It is bad.  I saw this one happen.
  2. ACPI engaged in the kernel.  I turned off ACPI in the kernel, my latency dived, performance rose, and ALSA confusion vanished.  This appears to occur with many motherboards.
  3. Sharing an IRQ between the motherboard sound and one or more other data-heavy systems, e.g., video.  This can be tricky to solve, it can require BIOS changes and/or PCI card position changes, and is not always possible for motherboard hardware.  Happily, a very good quality PCI implementation of recent version — 2.3 I believe — should not exhibit this problem at all, if both card(s) and motherboard are compliant.  I didn’t see this one happen (my motherboard and card are new), but read about it a lot in trying to solve my problems.
  4. Attempts to write to the same ALSA device by two different apps simultaneously.  ALSA docs say the problem doesn’t exist because the ‘dmix’ plugin is automatically engaged at need, but it’s simply not factual, it just does not happen in a great many cases, and my new very-low-noise pro audio sound card is one of them.  I solved this one by permitting only Jackd to output directly to the ALSA device; everything else outputs either to ALSA’s Pulse driver (thus far working very well indeed) or to Pulse (itself designed to handle multiple streams), which then hands the data to Jackd, which is tremendously good at handling multiple streams, at the very low latencies which we need.  My methods for this are described here.
  5. Device ID confusion.  I found that ALSA sometimes gets very confused about its hardware when one is using USB devices (e.g., a USB MIDI cable) which it knows about.  I’m pretty sure I saw it try to output sound to the MIDI device as well as the sound system, simultaneously, until after I rebooted twice, one very scary five-minutes-to-go moment; prayer was involved.  I solved this one by use of alphanumeric names (see this page) instead of either “default” or “hw:0″ etcetera in qjackctl, Jackd, and sometimes asound.conf / .asoundrc.

29 OctALSA and Jack Cooperate using PulseAudio

One of my principal problems to solve, has been how to get ALSA and Jack to cooperate in both (a) the high-test live audio milieu, where latency has to be low, responsiveness immediate, and bloat minimal, and (b) the general audio milieu, where we have to cooperate with the myriad API needs of general multimedia applications.  Some will do ALSA only, some prefer other things.  What to do?

And for high-test audio, jackd has to be given total access to its audio hardware, without impediment.  Jackd uses ALSA as its driver set — but jackd must not be required to share its channels, or we are defeating our first purpose.  So the easiest method, really, is to have two sets of audio hardware, perhaps USB speakers for the general multimedia and a pro-audio sound card with RCA jacks for the high-test work.  But let’s say we don’t want to have the extra hardware lying around; we want everything to go to the PA!  What then?

Well, general multimedia applications usually do not use Jackd.  They usually want to talk either directly to ALSA as jackd does, or more and more often as an alternative, something else called PulseAudio.

But the simplest approach appears to try to configure everything to use ALSA.  There was an attempt to solve this problem called an “ALSA Jack plugin”, which focusses on the fact that jackd must not share its ALSA hardware output.  When this is implemented,  jackd application sound still runs appropriately — still straight out, App–>Jack–>ALSA–>hardware — but general non-jackd ALSA application sound then runs App–>ALSA–>Jack–>ALSA–>hardware. There is no theoretical reason why this shouldn’t work very well; unfortunately the ALSA Jack plug-in has bugs. In my testing, it worked fine for several hours of system uptime, but then lost sync or cohesion or something, and began introducing static into the stream, gradually increasing in latency and xruns and quality decreasing over time. It would return to good behavior after reboot, and then after hours of either use or idleness, begin acting up again.

I would love to see the ALSA jack plug-in fixed — I don’t like adding layers to my systems — but we should use what works best.  I could just add a set of USB speakers…but meanwhile, while I am waiting to be healed from my bad cold, perhaps I can get this thing to work :-)   It appears I need to do what the desktop distros are doing:  I need to add PulseAudio.

PulseAudio is a layer, a program which sits quietly and takes up resources as needed.  I am surprised and happy to report that it sits most quietly, and has not disturbed any of the many apps I need.  It has also served its purpose quite well:  it is the “glue” which is permitting many apps to understand how to use the audio on my systems.  It would be rather unhelpful to try it on a box with 256M RAM — it seems to be using about that much RAM doing nothing right now — but as I have 4G here, that is OK.  If you have 1G RAM or less, or a slow CPU or slower RAM, go buy yourself some USB speakers and call it done :-)

But continuing.  This post is written for Debian Testing and its very close relatives.  It  presumes that you already have a working Jack audio setup, that you have identified the alphanumeric ALSA name of your audio hardware, and that Jack is using that alphanumeric name in its device configuration.  Here is a post containing info about alphanumeric names.

Commencing:

First you’ll need to get the PulseAudio packages. pulseaudio, pulseaudio-module-jack, and pulseaudio-utils, plus all dependencies.  You’ll also need the ‘sudo’ package.

Now get to root privileges (su or sudo -s), go to /etc/pulse, create directory “originals” and copy everything into there as a backup.  Then:

system.pa and default.pa should be made the same, should both contain:

#!/usr/bin/pulseaudio -nF
#
load-module module-jack-sink
load-module module-jack-source
load-module module-native-protocol-unix
load-module module-stream-restore
load-module module-default-device-restore
load-module module-rescue-streams
load-module module-suspend-on-idle
.ifexists module-gconf.so
.nofail
load-module module-gconf
.fail
.endif
.ifexists module-x11-publish.so
.nofail
load-module module-x11-publish
.fail
.endif

daemon.conf should remain the same, except for one line, originally reading:

; daemonize = no

Change it thusly:

daemonize = yes

The above will attempt run Pulse in an appropriate fashion, at boot.  But if you reboot right now, it will try to latch onto a Jack process which isn’t there.  So we need to run Jack at boot too.  With Jack (perhaps through qjackctl) running and working properly, do this in a command shell:

ps aux | grep jackd

On my machine, I get:

jeb       3777  1.8  0.7  29388 29404 ?        S<Lsl 09:58   0:59 /usr/bin/jackd -Z -R -t1000 -dalsa -dhw:HD2 -r96000 -p128 -n2 -s -m -Xseq -H -M
jeb       7139  0.0  0.0   3188   728 pts/1    R+   10:52   0:00 grep jackd

The info I need is therefore:

/usr/bin/jackd -Z -R -t1000 -dalsa -dhw:HD2 -r96000 -p128 -n2 -s -m -Xseq -H -M

We need to put this into /etc/rc.local.  My /etc/rc.local reads:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

sudo -u jeb taskset -c 1 nice --adjustment=-19 /usr/bin/jackd \
  -Z -R -t1000 -dalsa -dhw:HD2 -r96000 -p128 -n2 -s -m -Xseq -H -M

exit 0

‘sudo’ comes in at this point, because Jack has to be run as the user I log in with, for permissions.  I am also using taskset for CPU affinity (I have a quad, -c 1 means really core #2), and nice -19 is near-absolute-max priority (I don’t like -20, the kernel should have some leeway).

The last step is relatively simple.  The following is the contents of /home/jeb/.asoundrc:

pcm.!default {
   type pulse
}

ctl.!default {
   type pulse
}

Now reboot. It is working for me rather nicely. Jack apps run well App–>Jack–>ALSA–>hardware, at absolute minimum latency; ALSA-only apps run App–>ALSA–>PulseAudio–>Jack–>ALSA–>hardware; and those apps that can do the PulseAudio API natively — a growing number — run App–>PulseAudio–>Jack–>ALSA–>hardware.

26 OctAll-purpose cure for many library errors and some random crashes

When you see library errors, but the libraries are there, make sure their locations are in this file:

/etc/ld.so.conf

and then run this as root (or using sudo):

ldconfig

ldconfig has been known to cure random crashes too.

26 OctKernel command-line overrides

Here are some handy ones.

If your system’s clock runs too fast as a virtual guest, try:

clock=pit

And if your system’s clock is too slow, one or both of these:

pci=noapic pci=nolapic

although if you are running a multicore CPU, I believe that one of them is necessary.

Here is one more useful to turn off the older-style power management:

pci=noapm

The following is reportedly very good if you have a new and well-behaved motherboard with PCI and PCIe, it enables a new protocol for IRQ sharing that actually works:

pci=msi

and some poorly behaved motherboards, or older PCI cards, need it explicitly off:

pci=nomsi

And apparently, for ACPI situations (motherboards after 2000 or so), there is a whole slew:

acpi=force

enable ACPI if default was offoff — disable ACPI if default was on (same as noacpi)

acpi=noirq

do not use ACPI for IRQ routing

acpi=ht

run only enough ACPI to enable Hyper Threading

acpi=strict

be less tolerant of platforms that are not strictly ACPI specification compliant.

All of this and much more, is in kernel-parameters.txt, which is part of kernel source, also installed with a kernel-docs package, and web-searchable. The one at the link below is kept very current:

http://www.mjmwired.net/kernel/Documentation/kernel-parameters.txt

26 OctDaemon (service) control

For RedHat, use /sbin/chkconfig .  For Debian, best is probably to install something called ‘rcconf’.

Debian has the usual runlevels, but doesn’t exactly use them; at full-blast-boot it seems to run at something called runlevel S, which is enough to drive people up the wall if they aren’t ready for it :-)   This does mean that non-Debian runlevel editors should not be installed onto Debian, even if packages exist, because badly munged boot will often result :-)

I’d love to have a way to quickly daemonize a binary, but haven’t found it yet :-)