Table of Contents
BE EVENTS: BEDEPOT RECENT ARRIVALS: 1. Free Be Winter Pack with Purchase of BeOS R4.5 2. Eric's Ultimate Solitaire Free Be Winter Pack with Purchase of BeOS R4.5 BeDepot is including a FREE BeOS Winter Pack with every BeOS R4.5 purchased NOW until Jan. 31, 2000. BeOS Winter Pack includes:
Offer good with purchase of BeOS R4.5 (English, French and German) and BeOS Bible Bundle through BeDepot.com only. Offer not applicable to BeOS 4.5 Upgrade. Supplies are limited so act now! <http://www.bedepot.com/products/be/beos.asp> Eric's Ultimate Solitaire If you like card games, you'll love Eric's Ultimate Solitaire. It fools you into believing that you're directly manipulating the cards. It pulls you in with its easy to use interface, and makes you forget that time is passing in the outside world. Full and Trial versions available in English, French, German, and Indonesian. Other languages coming soon. <http://www.bedepot.com/products/Wildcard/EUS.asp>
BE SMALL COMMERCIAL & CORPORATE DEVELOPERS DISCOUNT: 1. BeBits Advertising - 30% off 2. Rainbow Productions Systems 10% Off BeBits Advertising - 30% off BeBits is offering a Banner Ad discount to Be Small Commercial and Corporate Developers until January 31, 2000. Regular: $25.00 CPM (cost per thousand)
If you are interested, contact bebits@bebits.com and mention your name, developer program level, and developer ID in your email. Rainbow Productions Systems 10% Off Rainbow Productions offers a line of premium computer systems. All come loaded with BeOS 4.5 and GoBe Productive 2.0. If you like, they can install one of the other operating systems as well. They offer local or nationwide delivery, and in some cases they can ship orders on the same day. Rainbow Productions is offering a 10% discount for Be Small Commercial and Corporate Developers on all of their systems. This offer is good now through January 31, 2000. If you miss the deadline, don't worry... they'll have different business packages available throughout the year 2000. Those who wish to take advantage of this offer should mention your Small Commercial or Corporate Developer ID at the time of purchase.
To upgrade to join the Small Commerical or Corporate Programs so you can take advantage of this and other discounts, go to <http://www.be.com/developers/> or email devprograms@be.com. BE DEVELOPER CLASSIFIEDS: Developers Wanted! Developers Wanted! Wildcard Design, Inc. We are looking for a few top notch developers to work on some of the hottest games on (and not yet on) the market! Please send your resume, along with any porting work you've done, your past/present work on the BeOS, etc. Network programming (especially under the BeOS) a plus, as is any gui and GL work. Mail your information to: jobs@wcdesign.com.
BE ENGINEERING INSIGHTS: Using C++ in the Kernel By Jeff Bush jeff@be.com
A while back, Ficus wrote a touching newsletter article about a kernel engineer venturing out into the big world of user space. As he didn't have time to finish his latest article before leaving for Christmas, he asked me to fill in for him, so I thought I would tell the mirror story. I am but a lowly apps engineer, comfortable in my world of object oriented code and fancy tools, and the kernel is a big, strange place. Perhaps the biggest oddity I find with the kernel is the lack of C++. No multiple virtually inherited templatized functors, nor polymorphic container iterators. Most kernel people I talk to shudder and turn white when I mention using C double-plus in the kernel. Undeterred, I'm going to write about issues that bear on doing just that. Be does not currently support C++ in the kernel, nor has it officially made any plans ever to do so. What I've been told (in a rather serious, fatherly tone) is that you should use C for drivers. So, with that disclaimer out of the way, and I hope without having brutally offended Cyril or Ficus (or any other kernel engineers; they're a very sensitive group), let's examine this more closely. A driver is nothing more than a shared library that's loaded by the kernel as an add-on. There are three requirements for a kernel add-on:
That's it. You may notice that this is a pretty broad definition. Language features such as name mangling, virtual method dispatch, and templates are not taken into consideration. That's because these things are totally internal to the compiler. The (gcc) compiler simply converts a text file containing a high-level language into a text file containing assembly language. The assembler knows nothing about C++ or its many colorful features. You can look at the assembly output of the compiler by using the -S flag for GCC. If you're unsure about the implementation of some feature, don't guess. Use -S and pick through the assembly. It can be very educational. For starters, I'll point out that using high-level libraries like STL is out of the question. Remember that memory used by the kernel is wired in place and can't be paged out like application memory can. This reduces the amount of physical memory available to the rest of the system. It can't be emphasized enough how very important it is to be frugal with kernel memory. Although, as mentioned earlier, the assembler (and consequently the binary) is language agnostic, it's important to consider the third point mentioned above. C++ is a little more runtime-library intensive than C. Certain low-level language primitives are partially implemented in a runtime library that is statically linked automatically with user space apps. The assembly output will have calls to these functions embedded when needed. For example: produces the following code on Intel (I've condensed it a bit): pushl %ebx pushl $4 call __eh_alloc addl $4,%esp movl %eax,%ebx movl $2,(%ebx) pushl $0 call __tfi pushl %eax pushl %ebx call __cp_push_exception addl $12,%esp call __throw movl -4(%ebp),%ebx The functions __eh_alloc, _tfi, __cp_push_exception, and __throw are implemented in a library. On Intel, this library is called libgcc.a. Also, certain C++ specific initializations are done when an image is loaded. The initialization code is implemented in crt0.o. These modules are linked into user space apps automatically. However, neither of these libraries gets linked into a driver. They can't, because they make assumptions about being in user space. Some important C++ features that are dependent on this runtime library support are:
There are two ways to work around the absence of these functions. One could avoid using the feature, or reimplement it in the driver in a kernel-friendly way. The latter can be more work, so consider carefully before embarking on this path. The runtime library is shipped with the compiler and statically linked into executables. Thus, if your driver runs on both platforms, you'll potentially have to implement the same feature for both Metrowerks and GCC, which usually differ in implementation. Worse, if some compiler implementation changed in some subtle way, in order to compile the driver with the new compiler, implementation of these runtime functions would have to be updated. It's probably best to avoid exceptions, for example. The current exception implementation on GCC generates a lot of large static tables when exceptions are enabled, and can increase the binary size significantly. I've seen increases of around 25% with exceptions enabled, and that's even if you never use them. As mentioned earlier, kernel memory is a precious resource, not to be taken for granted. Also, the effects of uncaught exceptions propagating out of your code and into the kernel proper are fatal. Besides, implementing the stack unwinding code in your driver would take a fair amount of work and be tedious to debug. 'new' and 'delete' are arguably important C++ features, and you'll probably want to implement them. Luckily, the compiler gives you an easy (and relatively portable) way to do this, by treating them as global operators. For example: void* operator new(size_t size, const nothrow_t&) throw() { return malloc(size); } void* operator new[](size_t size, const nothrow_t&) throw() { return malloc(size); } void operator delete(void *ptr) { free(ptr); } void operator delete[](void *ptr) { free(ptr); } Note the use of nothrow. This is defined in the <new> header. This is important for handling out of memory conditions. You'll need to call new like so: SomeClass *obj = new (nothrow) SomeClass; if (obj == 0) // handle this politely This version of new will generate code to check that the returned pointer is not NULL before calling your constructor or setting vtable pointers (which occurs before your constructor is invoked). You'll have to check to see if the result is NULL anywhere that you call new and handle it properly. Note also that if you have instance variables that are objects, you must be very careful to check and make sure they initialize properly. This is very subtle, but very important. The handler for pure_virtual is just a C function. It can be implemented simply as extern "C" void pure_virtual() { panic("pure virtual function call"); } This generally only happens when something is really hosed anyway, say, if you've trashed memory. But you'll get a linker error if you don't include it. Finally, if you have declare global instances in your driver, their constructors will *not* be called (ever). It's probably not a good idea to do this anyway, as initialization order in a driver is generally important, and it is fragile to depend on the compiler to initialize things in a predefined order. It's cleanest and most prudent to explicitly instantiate everything. It's important to mention that we often use a two- component driver model in BeOS, where a user level add-on lives in a server, with a smaller portion in the kernel. It's generally better to put all your C++ in the user level add-on and write a thin driver in C to bang registers and handle interrupts. This model can be faster (as you can perform certain operations on the driver without having to enter the kernel), more memory friendly (because the code in user space is swappable), and more stable, because bugs in the user level add-on are potentially less fatal. As you can see, writing a driver in C++ is more complex than writing one in C. The official Be-sanctioned practice is to write drivers in C, keeping them small and simple. However, it's important to understand the issues involved. Source Code: <ftp://ftp.be.com/pub/samples/drivers/alphabet.zip>
DEVELOPERS' WORKSHOP: BeOS Driver FAQs (Part 1) By Todd Thomas tt@be.com
Over the years, Be tech writers and engineers have produced a substantial amount of prose and sample code on the subject of drivers for the BeOS. Really. The problem is that it's not so easy to find it all. Enter the BeOS Driver FAQs, which will give you a crib sheet that should provide concise answers to your basic questions and serve as a launching pad for your deeper explorations of the BeOS driver universe. This document is making its initial appearance here in the Newsletter, but will soon go to live in the Be Book's "Drivers" section <http://www.be.com/documentation/be_book /Drivers/intro.html>. Without further ado, I give you the BeOS Driver FAQs (Part 1). Look for Part 2 in the next Newsletter. Drivers *What is a driver? In general, a driver is software that directly controls a hardware device, and may also provide an interface to the device for higher level software. In BeOS parlance, a driver is one of three types of kernel add-ons. The other two are modules and file systems. As add-ons, drivers, modules, and file systems can be loaded and unloaded by the kernel as needed at runtime. For more information on drivers, see "Device Drivers"
<http://www.be.com/documentation/be_book/Drivers
/Intro.html> and "Writing Drivers"<http://www.be.com
/documentation/be_book/Drivers/writing_drivers.html> in
the Be Book. Also, you must read Jon Watte's article
"Using and Writing Device Drivers on the BeOS" <http://
www.be.com/aboutbe/benewsletter/volume_III/Issue7.html#Workshop>
in the Be Newsletter (a newer version is available at
<http://www.b500.com/bepage/driver.html>. It has very useful
discussions of topics not strictly related to the interface
in < * Where do BeOS drivers live? The driver binaries that ship with BeOS live in
For access from user space, the driver is published in
the appropriate locations in the * What is the driver API? Drivers must implement the API declared in <drivers/Drivers.h>, which has two parts. One part is used by devfs <http:// www.be.com/documentation/be_book/Drivers/Intro.html#devfs> to manage the driver and publish it in the /dev hierarchy. This part consists of the following exported symbols: Called when the system is booted, to let the driver detect and reset the hardware. Called when the driver is loaded, so it can allocate needed system resources. Called just before the driver is unloaded, so it can free allocated resources. Called to obtain a list of device names supported by the driver. Called to obtain a list of pointers to the hook functions for a specified device. This exported value tells the kernel what version of
the driver API it was written to, and should always be
set to Only typedef struct { device_open_hook open; device_close_hook close; device_free_hook free; device_control_hook control; device_read_hook read; device_write_hook write; device_select_hook select; device_deselect_hook deselect; device_readv_hook readv; device_writev_hook writev; } device_hooks; Thus you can manipulate a driver from kernel or user
space by using the API defined in < Some drivers may also implement a third kind of API:
standard opcodes for the control hook function (which maps
to There are also suites of opcodes that must be supported
by devices wishing to conform to specific Be protocols.
For example, a driver that wants to be compatible with the
multichannel audio media node discussed in Jon Watte's
article "Do You Have 24 Ears" <http://www.be.com/aboutbe
/benewsletter/volume_III/Issue49.html#Insight> needs to
support the opcodes defined in For complete documentation of the driver API, see "Writing Drivers" <http://www.be.com/documentation/be_book/Drivers /writing_drivers.html> in the Be Book. * Where can I find driver sample code? In Modules * What is a module? A module is a kernel add-on that exports an API for use by drivers or other modules. This API cannot be accessed from user space. A module is useful for providing services to a class of similar devices so that each device's driver does not have to implement those services independently. Modules can also provide services to other modules. For more information about modules see "Writing Modules" (http:// www.be.com/documentation/be_book/Drivers/writing_modules.html) and "Using Modules" (http://www.be.com/documentation/be_book/Drivers/ using_modules.html) in the Be Book. * What is an example of a module? Every binary in the For example, in On its backend, the USB manager interfaces with another
example of a module -- a bus module -- which knows the
implementation details of a particular USB host controller.
For example, Another example of a module is the Atomizer, which implements a virtual device that returns a unique token for a null- terminated UTF8 string. In this case, a module is being used not to support hardware devices, but to extend the logical feature set of the kernel. For more information on the Atomizer module, see Trey Boudreau's article, "Creating Your Own System Services -- the Modular Way" <http:// www.be.com/aboutbe/benewsletter/volume_III/Issue30.html#Insight2>. * Where do modules live? Two BeOS modules -- the PCI and ISA bus managers -- are built into the kernel. All other BeOS modules live in the directories found in
* How do I use a module? Call Here's a quick chunk of sample code that demonstrates how to use the PCI bus module to see if your device is on the bus: #include <drivers/PCI.h> char pci_name[] = B_PCI_MODULE_NAME; pci_module_info *pci; pci_info info; int ix = 0; if (get_module(pci_name, (module_info **)&pci) != B_OK) { // handle error } while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { if (info.vendor_id == YOUR_VENDOR_ID && info.device_id == YOUR_DEVICE_ID) { // device is on the bus } ix++; } put_module(pci_name); * Where are public module API header files located? All public module API headers are found in
Bus Managers PCI: PCI.h ISA: ISA.h SCSI (via Common Access Method): CAM.h USB: USB.h Miscellaneous Atomizer: atomizer.h area_malloc: area_malloc.h * Where can I find module sample code? Module sample code is mixed in with the driver sample code at <ftp://ftp.be.com/pub/samples/drivers>, although it should get its own directory soon. atomizer.zip and xyz5038.zip are good starting points, while buslogic.zip and symbios.zip contain working bus modules for actual SCSI controllers. Look for BeOS Driver FAQs (Part 2) in the next Newsletter.
1997 Be Newsletters | 1995 & 1996 Be Newsletters Copyright © 1999 by Be, Inc. All rights reserved. Legal information (includes icon usage info). Comments, questions, or confessions about our site? Please write the Webmaster. |