figure 1: header file showing version numbers.

#define PMC_VERSION_MAJOR0x03

#define PMC_VERSION_MINOR0x00

#define PMC_VERSION_PATCH0x0000

 

fact that there are version numbers. The engineer clearly knew his software would be modified not only by himself but also by others, and he has specifically allowed for that by having major, minor, and patch version numbers. Simple? Yes. Found often? No.

The next set of lines—and remember this is only the first file I opened— were also instructive, as shown in Figure 2. Frequent readers of KV might think it was the comment that made me happy, but they would be wrong. It was the translation of constants into intelligible textual names. Nothing is more frustrating when working on a piece of software than having to

remember yet another stupid, usually hex, constant. I am not impressed by programmers who can remember they numbered things from 0x100 and that 0x105 happens to be significant. Who cares? I don’t. What I want is code that uses descriptive names. Also note the constants in the code aren’t very long, but are just long enough to make it easy to know in the code which chip we’re talking about.

Figure 3 shows another fine example from the header file. I’ve used this snippet so I can avoid including the whole file. Here, machine-dependent structures are separated from machine-independent structures. It would seem obvious that you want to separate the bits of data that are specific to a certain type of CPU or device from data that is independent, but what seems obvious is rarely done in practice. The fact that the engineer thought about which bits should go where indicates a

 

figure 2: translation of constants into descriptive names.

/*

* Kinds of CPUs known */

#define __PMC_CPUS() \ __PMC_CPU(AMD_K7, “AMD K7”) \ __PMC_CPU(AMD_K8, “AMD K8”) \ __PMC_CPU(INTEL_P5, “Intel Pentium”) \ __PMC_CPU(INTEL_P6, “Intel Pentium Pro”) \ __PMC_CPU(INTEL_CL, “Intel Celeron”) \ __PMC_CPU(INTEL_PII, “Intel Pentium II”) \ __PMC_CPU(INTEL_PIII, “Intel Pentium III”) \ __PMC_CPU(INTEL_PM, “Intel Pentium M”) \ __PMC_CPU(INTEL_PIV, “Intel Pentium IV”)

high level of quality in the code. Read the descriptive comments for each element and the indication of where the proper types can be found, as in the case of pmd_cputype being from enum pmc_cputtype.

One final comment on this file. Note that the programmer is writing objects in C. Operating system kernels and other low-level bits of code are still written in C, and though there are plenty of examples now of people trying to think differently in this respect (such as Apple’s Mac OS X drivers being written in C++) low-level code will continue to be written in C. That does not mean programmers should stop using the lessons they learned about data encapsulation, but rather that it is important to do the right thing when possible. The structure listed here is an object. It has data and methods to act upon it. The BSD kernels have used this methodology for 20-plus years at this point, and it’s a lesson that should be learned and remembered by others.

These are just a few examples from this code, but in file after file I have found the same level of quality, the same beautiful code. If you’re truly interested in seeing what good code looks like, then I recommend you read the code yourself. If any place is a “ happy place,” it is in code such as this.

KV

figure 3: machine-dependent structures are separated from machine-independent structures.

/* * struct pmc_mdep * * Machine dependent bits needed per CPU type. */

P.S. Complete code cross-references for many operating system kernels, including FreeBSD, can be found at http://fxr. watson.org/ and the code you’re looking for can be found at: http://fxr. watson.org/fxr/source/dev/hwpmc/.

A similar set of cross-references can be found on the codespelunking site: http://www.codespelunking.org/ freebsd-current/htags/.

 

struct pmc_mdep { uint32_t pmd_cputype; /* from enum pmc_cputype */ uint32_t pmd_npmc; /* max PMCs per CPU */ uint32_t pmd_nclass; /* PMC classes supported */ struct pmc_classinfo pmd_classes[PMC_CLASS_MAX]; int pmd_nclasspmcs[PMC_CLASS_MAX];

/* * Methods */

int (*pmd_init)(int _cpu); /* machine dependent initialization */ int (*pmd_cleanup)(int _cpu); /* machine dependent cleanup */

Dear KV,

In his book The Mythical Man-Month, Frederick P. Brooks admonishes us with grandfatherly patience to plan to build a prototype—and to throw it away. You will anyway.

At one point this resulted in a fad-of-the-year called prototyping (the programming methodology formerly known as trial and error), demonstrating that too little and too much are equally as bad.

References:

http://fxr.watson.org/

http://fxr.watson.org/

http://fxr.watson.org/fxr/source/dev/hwpmc/

http://fxr.watson.org/fxr/source/dev/hwpmc/

http://www.codespelunking.org/freebsd-current/htags/

http://www.codespelunking.org/freebsd-current/htags/

Archives