Re: kernel_thread from interrupt service routine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

jhoney jhoney a écrit :

> My requirement is like this. I am calling some blocking calls. if I create one 
> thread for one blocking call, another blocking call comes with is not adding to 
> the task list when I used tasklet. So I am going to threads now.
> 
> If I call threads from interrupt service routine, the arguments are not getting 
> passed correctly  to the thread. How to make interrupt service routine small and 
> spaw new thread for each call.

You don't want to spawn a thread for each call. You want to add stuff in
to a global list, and then wake up the thread so that it will process
the stuff. Depending on what you need to do, you can either use a thread
or a tasklet. I think you should prefer tasklets whenever possible, but
kernel experts of the list will confirm or infirm this.

Here some sort of pseudo-code (no error checks, never compiled, may be
completely wrong):

struct job_description {
  /* Here you have the values you need to process your job */
};

semaphore_t thread_sem;
struct job_description *job_list;
spinlock_t job_list_lock;

void my_thread (void *) {

  while (1) {
    struct job_description *job;
    struct job_description *local_job_list;

    /* Wait to be woken up by interrupt handler */
    sem_down_interruptible (& thread_sem);

    /* Get a local pointer to the list, and release the
       spinlock as sooas possible, so that the interrupt
       handler can add more jobs to the global list. */
    spinlock_lock (& job_list_lock);
    local_job_list = job_list;
    job_list = NULL;
    spinlock_unlock (& job_list_lock);

    /* Do the job, and free the structures */
    list_for_each_safe (local_job_list, job) {
      /* Do what you need with the job, with the data in
         the 'job' structure */
      list_remove (job);
      kfree (job);
    }
  }
}

int interrupt_handler (int num) {
    struct job_description *job;

   /* Fetch your info */

   /* Allocate job description structure */
   job = kmalloc (sizeof(struct job_description), GFP_ATOMIC);

   job->... = ...
   job->... = ...

   /* Add job to the global list */
   spinlock_lock (& job_list_lock);
   list_add_tail (job_list, job);
   spinlock_unlock (& job_list_lock);

   /* Wake up the thread */
   sem_up (& thread_sem);
}

int module_init (void) {
  sem_init (& thread_sem);
  spinlock_init (& job_list_lock);
  kernel_thread (my_thread);
  return 0;
}

Here we go.

Thomas
-- 
PETAZZONI Thomas - thomas.petazzoni@xxxxxxxx
http://thomas.enix.org - Jabber: thomas.petazzoni@xxxxxxxxx
KOS: http://kos.enix.org/ - SOS: http://sos.enix.org
Fingerprint : 0BE1 4CF3 CEA4 AC9D CC6E  1624 F653 CB30 98D3 F7A7

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux