CSE 451
Introduction to Operating Systems

Autumn 1998


Assignment 1 FAQ

> why do I get the following message?
> ct: can't open /etc/uucp/Devices
You are not executing the program named 'ct' in your current directory, but rather one that lives somewhere else in your $PATH variable. Typing './ct' will execute the copy in the current directory. This is a Unix-related question, and your classmates can probably provide quicker answers to other questions of this type than I can. The same goes for C related questions.


> why do we need return value from callout_register()? Do we need
> to inform the user when a event is successfully registered when
> a non-zero value is returned. What exactly is for that return value?
Take a look at the parameter list for callout_unregister().


> My other question is about the testing part. "generate 10000
> callouts" refers to accessing the callout data structure 10000
> times, or does it mean registering 10000 seperate callouts?
It's YOUR benchmark, so YOU get to decide. This benchmark will be different for the 'simple', 'complex', and 'stress' tests. Be sure to document WHAT your benchmark is and WHY you chose it.


> what does "closure" mean?
In my opinion, this is a poorly named variable (I am free to say this since this is not my code). Referring to page 44 of the dinosaur book, system calls sometimes require additional information to execute. In main.c, we see that 'strdup("SOME_STRING")' is passed as the third argument to callout_register(). This evaluates to a memory reference when the callout_register() function is called. The closure parameter is not a function call.

In the example code, the closure is passed to the callback function, and is eventually used by info().



> do we assume only one event handler per each event type, so
> each queue will have exactly one node in it?
No. The system already supports more than one handler per event. Do not reduce functionality in your implementation.


> If more than one callout is registered under an event type,
> are the functions in each callout in that event type's queue
> executed when that event occurs?
Yes. Execute every callout handler registered for that event. NOTE that the system already supports more than one function per event type - your job is to make it more efficient, not to change its behavior.


> Should we deallocate a callout_event_data and its closure
> (string) when it is unregistered, or do we keep it so we
> can use it in our statistics?
The closure is not really a string, but a void pointer. You should assume that whoever allocated the memory will deallocate it (even though this is not the case in the code you were given).


> What is the callout_map function for, does it call the
> callout_map_func_t on every callout_event_data in the
> system?
callout_map can be used to map a given callout_map_func_t over all of the callout functions. It would typically be used to find something in the callout table, or to print out some other statistic. Basically, you want to systematically traverse the data structure that contains all the registered callouts and execute the callout_map_func_t (received as a parameter to callout_map) on each registered callout.

The map function is only executed when you explicitly call it, not whenever an event is received. Hopefully the example makes more sense now.



> Why is everything cast to a "void*"? Why does almost
> every type name have an "_t" at the end of it?
The typedef'd data types are aliases for void *. In order to avoid compiler warnings about type mismatch, everything is cast from its real type to void *. The callout types are defined as void * to be as generic as possible. Ending the type name with an _t is a common coding convention for user defined types.


> Could you please explain more about true handles?
The only function this applies to is callout_register. This function returns a callout_id_t (the callout handle). This type is really a void *, in other words, a reference. In the current implementation, the handle is actually a pointer to an instance of callout_event_t contained in the event list. This is bad - a program that registers a callout can then use the handle returned to modify the internal callout system data structures.

A true handle is a name that maps to a real data structure, but does not allow access to the structure *except* through accessor functions. You could also call the handle a unique identifier.



> Can we remove the printf statements when measuring performance?
Your tests (simple, complex, stress) will not only measure performance, but also correctness. The info() function and printf statements will be useful to show correctness (for example, each callout for an event has a unique closure), so leave them in place. (Consider the cost of a printf to be representative of the work required in a callback.)


> Do I need to use gettimeofday() or is time() okay?
> How do I use gettimeofday()?
You should not use time() since the function has been obsoleted by gettimeofday(). Further, gettimeofday() has microsecond accuracy, while time()'s precision is on the order of seconds.

The man pages ('man gettimeofday') contains lots of useful information. Briefly, the timeval struct contains two fields: tv_sec (seconds) and tv_usec (microseconds). Since you're uninterested in timezone information, you can pass null in as the second parameter to gettimeofday(). To compute the difference, you'll have to do the math yourself.



> should our main handle the case just "./ct"
> afterwards (the case that came w/ the skeleton
> file). or should we just print out error
> message saying you need "-t and testfile name"
It doesn't matter as long as the -t option works. If you want to add or remove other options, be sure to update the usage message.