Issue 4-19, May 12, 1999

Be Engineering Insights: Attention Driver Writers!

By Cyril Meurillon

Starting with the Genki Beta 6, the kernel is a bit more strict about the way kernel add-ons, such as drivers and bus managers, use spinlocks and disable interrupts. In the past, if your driver violated one of the rules listed below, the kernel wouldn't complain—but you would degrade performance or even lock up the entire system. Now, if your driver does the wrong thing, the kernel panics. The solution: Clean up your driver code.

If you have any questions about the principles described below, don't hesitate to ask us: mail to devsupport@be.com.

Spinlocks

Spinlocks are used to synchronize code; so are semaphores. But the way they achieve this synchronization isn't the same: Spinlocks "busy wait"; semaphores don't. Busy waiting isn't good. However, acquiring a semaphore while handling an interrupt is forbidden. Therefore:

  • Use spinlocks to protect the critical section in an interrupt handler function.

  • Use semaphores everywhere else.

Spinlock-protected critical sections should be executed with interrupts disabled. It isn't necessary to explicitly disable interrupts in spinlock-protected critical sections used only by interrupt handlers, because they are invoked with interrupts already disabled.

Here's what you can do when you're inside a spinlock:

  • You can touch hardware registers (through bus managers hooks).

  • You can touch memory that's locked down.

  • You can call the following functions: kernel: system_time(), atomic_add(), atomic_or(), atomic_and() bus managers: read_io<size>() write_io<size>()

Everything else is forbidden.

Together, everybody: EVERYTHING ELSE IS FORBIDDEN.

Disabling Interrupts

The only time you should ever disable interrupts is when you're about to enter a spinlock-protected critical section. (If you think you need to disable interrupts for another reason, we'll tell you why you're wrong. Mail to cyril@be.com.)

If you must disable interrupts, you should re-enable them as quickly as possible. In no case should you leave interrupts disabled for longer than 50 microseconds. This means that your interrupt handler code—which runs while interrupts are implicitly disabled—must execute within that 50 microseconds.

If you have interrupts disabled, but you're not inside a spinlock, you can do these things (in addition to the spinlock-safe calls listed above):

  • release_sem_etc() with B_DO_NO_RESCHEDULE as flags.

  • get_sem_count()

  • add_timer(), cancel_timer()

  • dprintf()

The principle here is that you absolutely must not block, directly or indirectly.

If you feel you need to call a function that is not in this list, discuss it with us at devsupport@be.com


Be Engineering Insights: Tool Tips

By Robert Polic

Windows has Tool Tips, Macintosh has Balloon Help, and the BeOS has, er, well, up to this point, nothing, in the way of context-sensitive help. To address this shortcoming I've written a ToolTip class that's easily integrated into a Be application. The Be version of tool tips behaves more like a Windows Tool Tip than a Macintosh Balloon. In other words, as you drag the cursor across different areas of a window, a small window pops up—after a settable delay—below and to the right of the cursor with a one-line description of the UI element. The tip is displayed until the cursor is moved again, the window or application is no longer active, or the settable hold-time is reached.

Source for the TToolTip class and demo application can be found at <ftp://ftp.be.com/pub/samples/interface_kit/ToolTips.zip>.

Integrating this class with your application is fairly straightforward. You'll first need to instantiate a TToolTip object. In the demo application provided, you do this in the constructor of the application and the pointer to the object is cached:

ToolTipDemoApp::ToolTipDemoApp()
               :BApplication("application/x-vnd.Be-Help"),
                fPrefWindow(NULL)
{
    // set up a rectangle, instantiate and show a new
    (window = new ToolTipDemoWindow(BRect(100, 80, 300, 152)))->Show();

    // instantiate the tooltip window but don't show it
    fToolTip = new TToolTip();
}

The next step is to override the MessageReceived() method of the application object to forward any B_SOME_APP_ACTIVATED, eToolTipStart or eToolTipStop messages to the TToolTip class:

void ToolTipDemoApp::MessageReceived(BMessage *msg)
{
    switch (msg->what) {
        // these messages need to be forwarded to the
        // TToolTip class
        case B_SOME_APP_ACTIVATED:
        case eToolTipStart:
        case eToolTipStop:
            fToolTip->PostMessage(msg);
            break;
    }
}

The last step is to replace any BControl objects (BButtons, BColorControl, BSlider, etc.) with the TToolTipControls equivalents. These objects look identical to the base class objects with the exception of taking a tip parameter after all required parameters:

view->AddChild(new TToolTipButton(BRect(10, 44, 90, 44),
    "tool tip button",
    "Quit", new BMessage(B_QUIT_REQUESTED), "Click this
    button to quit"));

view->AddChild(new TToolTipButton(BRect(110, 44, 190, 44),
    "tool tip button",
    "Preferences", new BMessage('PREF'), "Click this
    button to set ToolTip preferences"));

Views other than BControls (BBox, BMenuField, BListView, BView, etc.) can also take advantage of the TToolTip class. To do this you'll need to sub-class the view you're interested in and override the MouseMoved() method. In the constructor of the view, cache the tip string:

TToolTipButton::TToolTipButton(BRect rect,
    const char *name,
    const char *label,
    BMessage *msg,
    const char *tip,
    uint32 resize_mask,
    uint32 flags)
   :BButton(rect, name, label, msg, resize_mask, flags), fIn(false)
{
    // cache the ToolTip string
    fTip = (char *)malloc(strlen(tip) + 1);
    strcpy(fTip, tip);
}

In the view destructor, stop displaying the tip if it's currently being displayed and free the cached tip string:

TToolTipButton::~TToolTipButton()
{
    // kill off any current ToolTip
    if (fIn)
        be_app->PostMessage(eToolTipStop);
    // free cached ToolTip
    free(fTip);
}

In the MouseMoved() method, determine whether the cursor is moving into or out of the view. If it's moving in, build a message that contains the start point and bounds of the view (both in screen coordinates) and the tip string, and post it to the application:

// if mouse has moved into our view, our window is active
// and it previously wasn't in, send a message to start the ToolTip
if ((Bounds().Contains(where)) && (Window()->IsActive()))
{
    if (!fIn) {
        BMessage    msg(eToolTipStart);

        msg.AddPoint("start", ConvertToScreen(where));
        msg.AddRect("bounds", ConvertToScreen(Bounds()));
        msg.AddString("string", fTip);
        be_app->PostMessage(&msg);
        fIn = true;
    }
}

If the mouse is moving out of the view, post an eToolTipStop message to the application:

// otherwise stop the message
else if (fIn) {
    be_app->PostMessage(eToolTipStop);
    fIn = false;
}

The TToollTip class is fully customizable as far as the font (and font size) used, the delay before the tip is displayed, the duration the tip is displayed, and most important, whether tool tips are enabled or not. To get the current settings:

tool_tip_settings settings;
fToolTip->GetSettings(&settings);

To apply the new settings:

fToolTip->SetSettings(settings);

tool tip settings is the following structure:

struct tool_tip_settings {
    bool        enabled;
    // flag whether tips are enables or not

    bool        one_time_only;
    // flag to only display the tip once per time in view

    bigtime_t   delay;
    // delay before tip is shown in microseconds

    bigtime_t   hold;
    // amount of time tip is displayed in microseconds

    BFont       font;
    // font tip is drawn in
};

Oh yeah, if you're going to add tool-tips to your application, please add a setting in your preference panel to enable or disable them.


Developers' Workshop: The Way Things Oughta BE

By Ken McDonald

X and I were waiting at the polo field for the rest of the Be documentation team when we noticed one of the interns running towards us from the direction of the Be campus, about 26 miles away. He reached us, held out a piece of papyrus rolled into a tube and stamped with the seal of Management, clutched his chest, and collapsed. It's nice to see dedication like that in a summer intern.

X unrolled the papyrus and scanned it quickly. “Oh, bother,” he said, “the developers are restless.

Hmm?” I said, sipping my Louis XIV Remy-Martin cognac. “What is it this time?

The normal tripe. 'All these great new features in the Be operating system, when do we get the documentation so we can start using them?', yada, yada, yada.” He looked over a couple of paragraphs in more detail, and sighed. “Still, I suppose we should do something about it. This is the third time in a month. It may call for drastic action.

Good lord, old boy,” I said, and swallowed, “you don't mean something like...cutting back on the recreational schedule!?

Of course not!”, said X, a look of shocked outrage spreading across his face. “That would mean forfeits in either the tennis or the yacht racing, and I'm certainly not going to give Stanford the pleasure!” He thought for a moment. “The big problem here is the engineers. They just keep writing more and more code that everyone wants to use. If we could somehow slow them down... Perhaps we could ask JLG to chain the engineers to their desks only twelve hours a day, instead of fourteen.

Nice idea, but it won't work,” I said, “most of them have never realized we lock them to their workstations, in the first place.

Oh, you're right,” he said, and then shrugged. “Well, what're you going to do? Let's not let it ruin the day. WAITER! Some more caviar and truffles over here, please...

<POOF!>

Ah, the daydreams of a Be technical writer. Sadly, however much the writing team at Be might deserve a scenario like the one above, reality is somewhat different. Not all the retin-A in the world can disguise the fact that the hard copy version of the Be Book is showing its age, and that someone who wishes to write code for the BeOS must collect information from many disparate sources in order to find out the real capabilities of the system. Let's not beat around the bush, either, but put the blame squarely where it lies—with the engineers, who in spite of being chained to their workstations, keep pumping out more and more clean, fast, useful code that needs to be documented before developers can use it. Add to this the fact that the doc team is about one-tenth the size of the engineering team, and that the kernel engineers have a tendency to steal any tech writer who knows enough to be useful, and well -- you get the idea.

The question then becomes, how to remedy this situation, so that the tech writers can enjoy the life of leisure they so richly deserve, without hindering the developers from getting on with developing?

Therein, Gentle Developer, lies the meat of this article. We're always looking for ways to get information to you more quickly and with greater accuracy. As the New Guy On the Block&trade; in the documentation team, I'm particularly looking for the best way that I can serve the development community. Comments and suggestions in general are welcome (please send any to ken@be.com). Also, I'd like to solicit your views on two possibilities I'm thinking about.

When I first arrived at Be, lo these two months ago, one of the first things I did was to write a tutorial on using the basic menu user interface functions. Now, menus are simple things, and you're all probably familiar with the functions to use and manipulate them. The idea behind writing the tutorial wasn't to explain menus, but to test out an idea that for most developers and most programs, the Be Book is overkill. You don't really need all of that information if a short tutorial presenting the commonly used functionality of the API is available. So, take a look at <http://www.be.com/developers/developer_library/tutorials/menu_tutorial.pdf > (sorry, currently available only in .pdf format), and see if you think you'd like to read more papers in a "tutorial series," similar to this one but on different topics. Because these tutorial documents wouldn't be as long as comprehensive reference documentation, we can write them (and update them) more quickly than the chapters in the Be Book. A likely next tutorial topic: Mouse Stuff, because certain important aspects of working with the mouse are terribly out of date in the Be Book.

The other possibility I'd like to mention is automatic document generation from C++ header files. Currently, header files are the "documentation of last resort" for the desperate developer—if you can't find what you need anywhere else, go look through the headers. Unfortunately, certain aspects of headers, like indexing and formatting, are not quite so perfect as they could be. Automatic document generation from the headers can solve some of these problems, and can also turn code comments into documentation paragraphs with just a bit more effort. To test this, I've edited the already excellent comments in the new C++ Network Kit API, and run those headers through an automatic doc generator. You can view the results <http://www.be.com/documentation/be_book/The%20Network%20Kit/ netapi_autogen/index.html>. If you'd like to see us work toward making the other APIs available this way (probably starting with the newest and working backward) let me know, and be sure to rate the usefulness of this compared to other documentation projects we could be doing.

Oh, and one more thing. If you could put "DOC FEEDBACK" as the subject line in any responses to this article, it'd let me use those cool Be attributes to easily organize my mail.


Modular Windows?

By Jean-Louis Gassée

This isn't about time travel and a return to the time when an earlier version of Windows Everywhere gave rise to such projects as Windows at Work and Modular Windows. (For history buffs, the head of that project was none other than Rob Glaser, now the CEO of Real Networks.) On second thought, my topic today is related to time travel, but to the future, to the After the Suit era. Specifically, I'll address some of the proposals for "remedies," for ways to level the playing field dominated by Microsoft.

I'll mention only briefly various structural remedies such as the "Baby Bills"—slicing and dicing Microsoft. There's the vertical way -- breaking Microsoft up into several smaller, identical competing entities. The horizontal way, on the other hand, attempts to separate slices of the Microsoft mille-feuilles: hardware, OS, applications, Internet services, and so on.

The horizontal overhaul gets very complicated in a hurry. Take one example: How do you create four competing OS companies? Do you allocate engineers, executives, and marketers, using an eenie, meenie, mynie, moe algorithm? If you decide to auction off the source code to other companies, what about the comments written on the wall of some forgotten bathroom stall? Who decides who gets the people who know where the good stuff is?

Different but no less interesting questions arise on closer evaluation of vertical slicing. As discussed before, drawing an actionable line between types of software is very difficult—perhaps intractable. Misunderstandings arise because we treat software as a thing—which, clearly, it isn't. Creating Baby Bells is relatively easy to conceive and execute because geographical regions and local loops have a physical reality that's easy to map into a corporate structure. Car radios have a physical reality and a unit cost, software doesn't. As a result, similes between the bundling of cars radios at the factory and the bundling of software modules are misleading.

Software is information of a special kind. Information on a newspaper page is inert. Software is "recombinant" information, it does something by itself and in combination with other software. Such difficulties are being recognized in Washington and, rather than attempt the mystifying task of defining what is part of an operating system and what's not, some sages are suggesting abandoning the pursuit altogether. Microsoft wants to stay free to innovate, they say, so let them do that—but let's dictate the conditions under which they do so.

Specifically, as Windows is extended, let's make sure it's done in a clear, modularized, well-documented way. The idea is to give competitors equal access to the system's plumbing and blueprints so they can write functional equivalents. This refers us back to the "motives and methods" issue discussed in an earlier newsletter More Browser Integration Bedtime Stories.

The tentacular method used by Microsoft in building a browser into Windows is viewed by some as a device, a way to maintain and extend its monopoly. The browser is difficult to remove—it is inextricably intertwined in the OS. This results in a barrier to entry by a competitor. Customers cannot remove the MS module and install the functional equivalent, the better, faster—or fatter, slower—module, thus letting the market work on a level playing field. Using the much discussed browser integration as an example, under the sages' proposal, Microsoft would create a browser in a "clean, well-lighted" way, making it easy to see where and how it connected to the system, implementing it as a well-delineated module. In that example, it would have been easy for Netscape to write an equivalent module that customers could easily swap for the MS implementation, lest we forget Netscape got there first.

Making Windows modular is a seductive proposal. It avoids the creation of roach motels by leveling access to system facilities and technical information and it does not prevent Microsoft from adding innovative features to Windows, it just limits its ability to use recombinant information as a way to maintain and extend its monopoly. But what will critics and/or Microsoft allies say? They'll probably start by claiming this type of disclosure is excessive, costly, slows them down, what about trade secrets, intellectual property... Critics will also ask pricing questions. A software module doesn't have much physical cost when added on an existing CD-ROM, thus giving the incumbent the ability to give it away and bleed its competition dry.

Others will introduce implementation issues, such as the need, real or tactical, to take three years and three thousand people in a separate building in order to disentangle and document Windows internals in compliance with the court order—by which time Microsoft will be Everywhere Else. The fact that there are pros and cons to this particular avenue of remediation is actually good news. When a proposal is all pro and no con—it's a con. There has been some debate of structural and contractual remedies, the latter being the easiest to implement, I hope we'll now hear a more detailed discussion of the modular approach.

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.