September 2006

The Browsenberg Uncertainty Principle

I hereby present my Browsenberg Uncertainty Principle:

As one increases the layout precision of a section on a webpage, all other sections of the page have their layouts perturbed by a proportional amount.

And its corollary:

The more precisely one specifies positioning and layout for a page in one browser, the less accurately every other browser will render it.

Personally, I think these need no further explanation. The sad fact remains, though, that people don’t seem to understand this — especially those who happen to want webpages created for them.

The process is familiar to anyone with a modicum of web development under their belt.

Insane Customer: I’d like this webpage designed! Here, I’ve forwarded you a bunch of pictures of what I want it to look like. Our designers took screenshots of their Photoshop mockup and faxed it to us, then we ran it through the photocopier a few times, scribbled over it in sharpie, scanned it in, and pasted it into a Word document which we then zipped and attached to this email. Let us know when you can complete it.
Three days pass…
Enlightened Developer: We’ve completed the project. Here’s screenshots of every page being rendered in eight different browsers (including IE 5, 6, and 7). Please give us feedback [Lines of HTML/JavaScript hacks, and CSS: 14]
Insane Customer: We need you to have all text rendered in [company’s own font, which nobody else in the world has because it was developed in-house by their just-as-insane design team; it also happens to be missing glyphs for the letters “t” and “e”]. Also, the left sidebar needs to be seven pixels shorter. And I need you to make sure that the bottom of every section lines up with the exact pixel where the text ends in the section next to it. Thanks.
Two weeks pass…
Enlightened Developer: Here’s the page with your modifications. Unfortunately, it no longer works in Opera, Lynx, or Konqueror. But few people use those browsers, so it should be okay. [Lines of HTML/JavaScript hacks, and CSS: 173]
Insane Customer: That looks better, but now the alignment of the header is off by three pixels, and some of the letters show up as weird boxes with numbers in them! This is unacceptable!!! We were expecting to deploy this site six days ago, and you’ve done nothing but cause excess delays. We need this ASAP!!!
A month passes, with back-and-forth between Customer and Developer…
Enlightened Developer: Okay, this should do it. We’ve got the layout down now, but had to drop support for IE5 and Safari, since they don’t support [random CSS tomfoolery without which some absurd requirement couldn’t be satisfied]. Also, the viewer will automatically have his display resolution set to 640×480, or else one of the text blocks will roll off the edge of the screen. We’re ready to deploy this as soon as you give us the okay. [Lines of HTML/Javascript hacks, and CSS: 1,027]
Insane Customer: Perfect. However, we’ve recently developed our own internal server-side blink tag, and our new Website Design Policy states that any place our logo is, we need to use it. It will require this 16,641 line JavaScript file to directly send some PHP and SQL to our Application Server, and these small (500 or so) CSS changes in order to incorporate the actual blinking. Can you have this incorporated by tomorrow?
Three days later…
Enlightened Developer: Okay, we tasked the entire company to this and had every developer work without interruption for sixty-three hours straight. We were able to complete these last requirements. Unfortunately, your code only works in IE 7, so we’ve dropped support for Firefox and IE 6. All your customers will be forced to download a 117MB browser upgrade. Plus, we’ll have to look into the security issues of your server-side blink; namely, if a customer accidentally clicks on your logo while it’s blinked out, it will empty the contents of your entire SQL database, and format your webserver. On second thought, ignore that. I think we have a solution for this entire situation. We’ll deploy today. [Lines of HTML/Javascript hacks, and CSS: 69,552]

I’ve often considered simply making webpages as static images. Links can be done by a giant image map covering the entire thing, and input fields can just be superimposed on top. Or we could train marketing and sales types to realize that their customers don’t want them explicitly controlling every aspect of their sensory input or even to comprehend the fact that HTML wasn’t designed to do such silly things, no matter how much JavaScript and CSS you layer on top.

Nah, the first option is probably far easier.

Technical

Comments (3)

Permalink

Writing a Threading Library

The first assignment for my Operating Systems class is to write a threading library for Linux. It’s not comprehensive, but it should support most of the “basic” functions: init, create, wait, join, exit, and so on. Plus, it should come with a mutex library for synchronization (which, coincidentally, it should use itself in order not to trip over its own toes).

It’s one of the first programming assignments I’ve had in awhile which I’ve really actually gotten into. The code itself is surprisingly straightforward, only nuanced. What I mean by that, I suppose, is that the algorithms for doing this aren’t too mentally taxing (yet), but the API I’m using (ucontext.h’s setcontext, makecontext, swapcontext, and getcontext functions) is completely foreign to me, as is the concept of signal handling in C. There’s an alternative (setjmp.h’s longjmp, siglongjmp, setjmp, and sigsetjmp functions) which is generally used for comprehensive threading libraries (I believe pthreads uses it, but I’m not positive), but it’s a bit more difficult, and what I’m using now is “good enough”. I may still change to the latter library, but only once I’ve gotten the current implementation working.

Anyway, ucontext. It abstracts the concepts that I need pretty well, but there’s some leaks. For instance, valgrind, a popular program analzyer, reports a bunch of “interesting” memory reads and writes, plus a few uses of uninitialized memory. Even though they’re (what I believe to be) completely valid (and the memory is initialized, dammit), the fact that contexts are being swapped and the code pointer is being thrown around all over the place seems to be throwing it for a loop. Maybe this is an issue with any threading library, though, and simply a limitation of our ability to analyze memory accesses. I don’t know.

The problems reported by valgrind don’t seem to be causing any functional. There are other more substantial issues, however. For instance, the concept of a “thread” is something I’m inventing on top of these contexts (the quotes will be used from now on to distinguish between my simulated “threads”, and the operating system’s understanding of a thread). Because of this, I ran into an issue with my program terminating. As it turns out, when setcontext switches to a context, and that context reaches the end of the function it was told to run, the thread exits. But not my “thread” — the actual kernel-recognized concept of the thread my application is running in. Oops.

It was reasonably easy to fix. You’re allowed to give a context another context to return to when it’s finished running. This is similar to a callback function, only it requires more memory and yet more code to initialize the context. And I have to create one for each “thread” (more on this later). So, I make a context which starts running a function that turns the currently-executing “thread” into a zombie and re-runs the scheduler. I will have needed this anyway, but it would have been nice not to have my entire program exit just because some context returned, but I can see why the API was designed this way; it’s not entirely clear what the context should do when it’s finished (you’re not really running multiple programs at once using these contexts, you’re simply saving a context’s state, then swapping to it when a scheduler is run; how should a context know what other context to go to when it’s done executing unless you specifically tell it?). I’m going to have to extend this zombie function later, though; once I implement wait, join, and the like, the thread will have different things to do when it terminates. For instance, when I join a thread, the thread should clean itself up entirely and get its return value back to the joiner. When it’s waited on, yield back to the waiter. And finally, when nobody seems to care about it, it has to sit around in a zombie state until the program exits, just in case another piece of code ever ends up referring to it later.

I mentioned earlier that I have to create a zombie context for every “thread” I make. I had hoped I could make one zombie context that they can all share, but initial attempts to do so have all failed; I’ll return to it later. Essentially, a context includes not only all the memory and stack of the program at that point in time, but also where the code is currently being executed (i.e., the code pointer). So when a zombie thread calls the function to zombify it, it enters the function and continues down. I haven’t found a reasonable way to “reset” the context to its original state, so other zombies which would swap to this context find themselves past the cleanup and zombification steps.

Another potential would be to create two zombie contexts. When one runs, it cleans up the other (which should theoretically no longer be in use, with proper mutex usage), reallocates the memory and creates a new, fresh zombie context, points the “current” zombie context to the newly-created one, and yields back to the scheduler. The next time a zombie is run, it uses the new context, frees and reallocates the (previously) old one, then points at that one again. I’ll try this approach whenever I have time.

Besides these issues, I’m proceeding quite quickly through the assignment. I’ll have to dedicate a lot of time over the weekend to it, but I’m not worried about the deadline, since I have nothing else due in the period (I do have one test, though). I’ve already implemented thread creation, grabbing the current thread handle (which is trivial in my implementation, so I might as well have) (note to self: I may want to use this function rather than referring to the current_thread pointer, just to be safe), scheduling, and thread cleanup. Only three of the several API functions I’m supposed to implement have been finished (i.e., create, get current thread, and init), but I have most of the actual threading code written, so writing the other publicly-exported functions should be relatively minor tasks that simply get or poke or manipulate the different structures I’ve already set up using functions I’ve already written. At least, I hope it’s that simple.

Technical

Comments (0)

Permalink