Understanding User and Kernel Mode

Most operating systems have some method of displaying CPU utilization. In Windows, this is Task Manager.


This is a companion discussion topic for the original blog entry at: http://www.codinghorror.com/blog/2008/01/understanding-user-and-kernel-mode.html

This article should be marked with a caveat that states that most of what it says applies only to .NET programs running on Windows on x86 hardware.

Exception functionality is not implemented uniformly across all programming languages on all operating systems. “Exceptions imply kernel mode transitions” may be true for C# on .NET on currently shipping Windows, but it’s certainly not true for all C++ implementations, nor for all Java implementations.

As a thought experiment, try making a list of every programming language that you can use for older operating systems which don’t utilize user mode, but simply run everything in the same privilege level as the kernel. Classic Mac OS on the 68000 CPU is a good example. How could exceptions imply a kernel mode transition then? (I’m not certain but I believe MS-DOS and older versions of Palm OS are additional examples of OS’s that lacked a distinction between user mode and supervisor / ring 0 privilege levels.)

There is some controversy as to whether exceptions are a bad idea for code clarity in general. I use them in cases of “this shouldn’t happen unless something is seriously wrong”, but I do not avoid them altogether. To boycott a programming language feature altogether just because you read some blog post saying it was slow is just a case of premature optimization. Prove that it’s slow for your architecture, or that it makes your code harder to maintain; otherwise you’re just a victim of (self-inflicted?) FUD.

@Jonathan Holland
BTW where/how did you get the reflection of TryParse() .

Disregard that comment.i figured it out myself (googled “reflector”).that tiny programme is a great tool.i’ll have alot of fun exploring .net libraries!thanks

Jamie Flournoy -
“This article should be marked with a caveat that states that most of what it says applies only to .NET programs running on Windows on x86 hardware.”

Hey, the entire blog should marked with that caveat. :wink:

Actually, I’ve heard some places used TUX to serve out static advertising landing pages for URLs they were sitting on, and I guess between the falling cost of hardware and the failing interest of kernel devs to touch it, TUX fell out of interest.

But this nonsense about software exception handling needs explanation. Between the intended audience (programmers who somehow don’t understand userspace / kernel space divisions) and the very light detail given, I can only assume for the moment that the statement about implying kernel transitions is bwrong/b.

For the many “exceptions don’t cause a transition to kernel mode” commenters, I refer you to Chris Brumme’s post, already linked by Mike Dimmick (thanks Mike)

http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx

Consider some of the things that happen when you throw an exception:

  • Grab a stack trace by interpreting metadata emitted by the compiler to guide our stack unwind.
  • Run through a chain of handlers up the stack, calling each handler twice.
  • Compensate for mismatches between SEH, C++ and managed exceptions.
  • Allocate a managed Exception instance and run its constructor. Most likely, this involves looking up resources for the various error messages.
  • Probably take a trip through the OS kernel. Often take a hardware exception.
  • Notify any attached debuggers, profilers, vectored exception handlers and other interested parties.
    ==

Operative words being “probably take a trip through the OS kernel.”

I’ll remember to stop throwing exceptions from now on!

Exceptions are OK, just don’t throw them in giant loops, control structures, or anywhere that performance is extra-super-critical. :slight_smile:

“Exceptions imply kernel mode transitions.”

In what sense? Most high level languages handle their exceptions completely in userspace. What does a language exception have to do with the kernel?

Obviously bus errors c involve the kernel - but they’re not the same as language exceptions.

Outside the kernel caching, I think you’re wrong on the perf impact of HTTP.SYS (and its ironic given what your article is about):

“Using HTTP.sys and the new WWW service architecture provides the following benefits:
…
• Requests are processed faster because they are routed directly from the kernel to the appropriate user-mode worker process instead of being routed between two user-mode processes.”

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/a2a45c42-38bc-464c-a097-d7a202092a54.mspx?mfr=true

So… you think that exceptions in .NET involve the CPU executing in kernel mode? WTF?

“Exceptions imply kernel mode transitions.”

You’re talking about OS exceptions, right?

if you can circumvent the use exceptions why not go ahead : for example in c# the TryParse () method is a good exception work-around .i have always had problems with exceptions because they are costly .i would say use them only when there is no other option or circumvention available.And throwing exceptions in a loop should be avoided at all times ,is it better to create a custom exception method and call it when needed.

Obviously, Jeff, you are confused by the identical name.

Hardware/CPU/OS/kernel exceptions are exceptions generated by the hardware and dealt with by the kernel, drivers, etc.

Language exception are a different mechanism altogether, that shares the same name, but is normally unrelated and is normally handled completely in user mode by the language VM or run time support library and the compiler. The reasons they are slow is basically their asynchronous nature which requires tracking of object lifetimes, and complicated stack unwinding (at least in C++).

An exception (heh) to this is the Structured Exception Handling mechanism invented and used by MS, which is maps certain kernel exceptions to software exceptions.

Please don’t lets cargo-cult the idea that exceptions are /always/ bad. As with any other technique, if performance is critical you should benchmark.

For language exceptions the performance costs break down into two broad categories:

  1. The cost of setting things up so it’s possible to throw an exception

  2. The cost of actually throwing an exception.

The first cost may be unavoidable - it depends on the language. For example some C++ implementations generate slightly faster function entry code if the compiler knows that it won’t subsequently have to unwind the stack due to an exception. Higher level languages tend to incur the ‘being able to handle an exception’ cost whether you actually throw an exception or not - and in general that cost will be small compared to whatever else the language is doing.

Actually throwing an exception will also take some time - how much depends on the implementation.

Measure then decide. Don’t cargo cult.

Jeff,

I’m not buying it. A one liner in a blog post that says “Probably take a trip through the OS kernel. Often take a hardware exception.” isn’t enough proof to say why exceptions are s o slow, especially when the rest of the things that definitely happen explain most all of the performance issues with exceptions.

Yeah, you shouldn’t use exceptions in performance intensive code, that we know. Perhaps you should trace the entire execution of a few types of exceptions (C#, C++, SEH, hardware) to actually see what happens.

So… you think that exceptions in .NET involve the CPU executing in kernel mode?

i’m not sure but it seems reasonable enough to be true ,possibly some of the .Net libraries are used in low level OS operations.Is this true?

This is what we extra-crashy-code-writing programmers like to call “progress”.

Haha! And to celebrate progress, I’ll write a couple (more) crashing bugs this afternoon :slight_smile:

I beleive he’s talking about Win32 exceptions.

Jeff, just to be clear: not all language exceptions require user/kernel mode transitions. There are three somewhat confusing ideas of “exceptions” here:

-Exceptions are a language feature in certain programming languages such as C++, C#, Java, and many scripting languages, for transferring control and triggering automatic stack unwinding. There’s no need for the kernel to get involved in a thrown exception caught by a try/catch block in general; the program can just save some information and jump to the handling code. The slowness of throwing and handling exceptions is generally due to implementations that trade off speed of entering try/catch/finally block with the speed of looking for exception handlers and handling an exception.

-Exceptions (more generally, structured exception handling or SEH) are a Windows operating system feature. They allow structures mirroring some languages’ try/catch or try/finally blocks to be used to handle things like page faults or memory access violations, which are raised from kernel mode, and also to handle application-raised conditions if desired. The exception handling blocks can be nested on the stack as deeply as you like. It’s not necessary to implement language exceptions using SEH, but you can. Visual C++ does. Visual C++ and the .NET CLR also translate certain kernel-raised SEH exceptions into language exceptions that can be detected and handled by try/catch blocks. For example, the .NET NullReferenceException is sometimes raised like this. Obviously, kernel-raised exceptions originate from kernel mode and need a mode transition, but user-raised SEH exceptions don’t: see http://www.nynaeve.net/?p=201 for an explanation of how this all works. Other operating systems use different mechanisms to communicate back to user mode; for example, Unix-like systems use “signals” for this purpose.

-Exceptions are the name for certain conditions detected by the processor, such as executing an illegal instruction, dividing by zero, or accessing memory “illegally”. A “machine check exception” is another example of this, where the CPU detects a hardware error. These cause the processor to immediately switch to kernel mode and run a piece of kernel code to handle the situation. In Windows, they may eventually result in an SEH exception being raised to user mode. There’s no idea of nested scopes or anything here; the processor just saves the address where the exception was triggered, and starts running kernel-mode code.

As you can see, the last category is the only one that requires an avoidable user/kernel mode transition, but it can be translated all the way back into the first category of exception.