OO missing in task queues and modules

From: Peter T. Breuer (ptb@it.uc3m.es)
Date: Sun May 07 2000 - 13:00:04 EST


The task queue and module interfaces are not sufficiently object
oriented (discussion bait). Feel free to tell me if that's not so.
Then I won't have to make the following hacks.

I would like to

1) make
         init(struct module *this)
   the type of the module init functions. They currently are of type
         init(void).

         atomic_set(&mod->uc.usecount,1);
- if (mod->init && mod->init() != 0) {
+ if (mod->init && ((void(*)(struct module*))mod->init)(mod) != 0) {
             atomic_set(&mod->uc.usecount,0);

or else change the struct definition to avoid the cast.

         struct module_ref *refs;
- int (*init)(void);
+ int (*init)(struct module *);
         void (*cleanup)(void);

2) put an extra field in struct tq_struct that points back to itself. I think
   that's required in order that the function that gets scheduled can
   be called as
         scheduled_function(struct tq_struct *this)
   or
         scheduled_function(void * data, struct tq_struct *this)
   instead of
         scheduled_function(void *data)

                        mb();
                        save_p -> sync = 0;
- (*f)(arg);
+ (*(void(*)(void*,struct tq_struct*))f)(arg, save_p);
                }

Again, there's a corresponding change in the struct type
that can be contemplated so as to get rid of the cast.

I've encountered this need while writing a module that removes itself
using the tq_timer queue to schedule its removal. The easiest solution
is for its init function to schedule free-module(this,0). But it needs
a pointer to the module struct. If I use the module name instead and
schedule delete_module(this_kernelspace_name), I still have to get hold
of the name. Easiest way to do that is to look at this->name. I can't
hard code it since the user may change it.

So I conclude that init_module needs the module struct as an arg.

Now to the task queues. I have to delete the module that scheduled the
delete. So I have to be careful what memory I use for the tq_struct
that gets placed on the queue. Using an automatic is out of the
question, and a static from the module is also dangerous. The safe
thing is to get the memory from kmalloc, and kfree it after removing the
module. Aha, but who runs the kfree? The module just disappeared. OK,
we need to hide the kfree call somewhere else. But it needs the address
of the tq_struct. How does it get it? It normally only gets passed
a single data address in run_task_queue.

The easiest solution is to change the run_queue fuction to run
scheduled_function(void *data, struct tq_struct *this) so that it can do
the stuff it wants to on its data and then call kfree(this). That
change preserves old code compatibility.

The result can be kludged by instead letting tq_struct->data be the
address of a struct containing data + the address of the real data, but
it's horrible. I've just done it, and I know.

This is a general problem. One needs to be able to get memory for a task
struct, place it on the queue, then release the memory. The obvious
place to handle the release is in run_queue. I'd like to see that interface
set up. But until then, as I suggested above, the scheduled function
must receive the address of its tq_struct.

Thoughts?

Peter

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun May 07 2000 - 21:00:21 EST