Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2007 Jan Hudecek
  3.  * Copyright (c) 2006 Jakub Jermar
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. /** @addtogroup genericddi
  31.  * @{
  32.  */
  33. /** @file
  34.  */
  35.  
  36. #include <arch.h>
  37. #include <config.h>
  38. #include <arch/types.h>
  39. #include <arch/asm.h>
  40. #include <ddi/tasklet.h>
  41. #include <synch/spinlock.h>
  42. #include <time/delay.h>
  43. #include <proc/thread.h>
  44. #include <panic.h>
  45. #include <print.h>
  46. #include <synch/waitq.h>
  47.  
  48. /** Timeout length in the tasklet thread */
  49. #define TASKLET_THREAD_SLEEPDELAY 500
  50. /** Priority of the tasklet thread */
  51. #define TASKLET_THREAD_PRIORITY 10
  52.  
  53.  
  54. /** Tasklet state enum */
  55. typedef enum  
  56. {
  57. TASKLET_STATE_NOTACTIVE = 0,
  58. TASKLET_STATE_SCHEDULED = 1,
  59. TASKLET_STATE_RUNNING = 2,
  60. TASKLET_STATE_DISABLED = 4
  61. } tasklet_state_enum;
  62.  
  63.  
  64.  
  65. /** Spinlock protecting list of tasklets */
  66. SPINLOCK_INITIALIZE(tasklet_lock);
  67.  
  68. /** array of tasklet lists for every CPU */
  69. tasklet_descriptor_t** tasklet_list;
  70.  
  71. /** Initializes tasklets - except for the tasklet thread */
  72. void tasklet_init(void)
  73. {
  74.     int i;
  75.     tasklet_list=malloc(sizeof(tasklet_descriptor_t*)*config.cpu_count,0);
  76.     if (tasklet_list==0)
  77.         panic_printf("tasklet list mem not allocated\n");
  78.     for(i=0;i<config.cpu_count;i++)
  79.     {
  80.         tasklet_list[i]=0;
  81.     }
  82.     spinlock_initialize(&tasklet_lock, "tasklet_lock");
  83. }
  84.  
  85. /**
  86. * Creates and runs the tasklet thread
  87. *
  88. *  @param kernel_task Pointer to the kernel task - for create_thread
  89. */
  90. void tasklet_run_tasklet_thread(task_t * kernel_task)
  91. {
  92.     thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, 0, "tasklet_thread", false);
  93.     if (t==NULL)
  94.     {
  95.         //wtf?
  96.         panic_printf("tasklet thread not created\n");
  97.     }
  98.     else
  99.     {
  100.         //dynamical priority should pick the best
  101.         //      t->priority = TASKLET_THREAD_PRIORITY;
  102.         thread_ready(t);
  103.     }
  104. }
  105.  
  106. /** Thread which keeps executing scheduled enabled tasklets
  107. * @param data not used
  108. */
  109. void tasklet_thread(void* data)
  110. {
  111.     waitq_t wq;
  112.     waitq_initialize(&wq);
  113.     while (true)
  114.     {
  115.         tasklet_do();
  116.         waitq_sleep_timeout(&wq,(uint32_t)TASKLET_THREAD_SLEEPDELAY,0);
  117.     }
  118. }
  119.  
  120. /** Initializes tasklet structure
  121. * @param func tasklet callback function to be called
  122. * @param data pointer to be passed to the tasklet function
  123. */
  124. tasklet_descriptor_t* tasklet_register(void (*func)(void* data), void* data)
  125. {
  126.     tasklet_descriptor_t* tasklet=malloc(sizeof(tasklet_descriptor_t),0);
  127.     tasklet->data = data;
  128.     tasklet->func = func;
  129.     tasklet->state = TASKLET_STATE_NOTACTIVE;
  130.     tasklet->next = 0;
  131.     return tasklet;
  132. }
  133.  
  134. /** Schedules the tasklet for execution on current CPU
  135. * @param t tasklet to be scheduled
  136. */
  137. void tasklet_schedule(tasklet_descriptor_t* t)
  138. {
  139.     spinlock_lock(&tasklet_lock);
  140.     //clear notactive, running and scheduled flags
  141.     t->state &= TASKLET_STATE_DISABLED;
  142.     //set the scheduled flag
  143.     t->state |= TASKLET_STATE_SCHEDULED;
  144.     t->next=tasklet_list[CPU->id];
  145.     tasklet_list[CPU->id]=t;
  146.     spinlock_unlock(&tasklet_lock);
  147. }
  148.  
  149. /** Tasklet will not be run, even if scheduled
  150. * @param t tasklet to be disabled
  151. */
  152. void tasklet_disable(tasklet_descriptor_t* t)
  153. {
  154.     spinlock_lock(&tasklet_lock);
  155.     //set the disabled flag
  156.     t->state |= TASKLET_STATE_DISABLED;
  157.     spinlock_unlock(&tasklet_lock);
  158. }
  159.  
  160. /** Tasklet will be run if scheduled
  161. * @param t tasklet to be enabled
  162. */
  163. void tasklet_enable(tasklet_descriptor_t* t)
  164. {
  165.     spinlock_lock(&tasklet_lock);
  166.     //clear the disabled flag
  167.     t->state &= ~TASKLET_STATE_DISABLED;
  168.     spinlock_unlock(&tasklet_lock);
  169. }
  170.  
  171.  
  172.  
  173.  
  174. /** Executes scheduled enabled tasklets */
  175. void tasklet_do(void)
  176. {
  177.     int i;
  178.     spinlock_lock(&tasklet_lock);
  179.     for(i=0;i<config.cpu_count;i++)
  180.     {
  181.         tasklet_descriptor_t* t = tasklet_list[CPU->id];
  182.         //empty the queue of tasklets
  183.         tasklet_list[CPU->id]=0;
  184.         while (t)
  185.         {
  186.             if (!(t->state & TASKLET_STATE_DISABLED))
  187.             {
  188.                 if (t->func)
  189.                 {
  190.     #ifdef DEBUG
  191.                     printf("tasklet - calling tasklet!!!\n");
  192.                     delay((uint32_t)1000000);
  193.     #endif
  194.                     t->state = TASKLET_STATE_RUNNING;
  195.                     t->func(t->data);
  196.                     t->state = TASKLET_STATE_NOTACTIVE;
  197.                 }
  198.                 else
  199.                     panic_printf("tasklet func NULL\n");
  200.             }
  201.             else
  202.             {   //return it back to the queue of scheduled tasklets
  203.                 t->next = tasklet_list[CPU->id];
  204.                 tasklet_list[CPU->id] = t;
  205.             }
  206.             t=t->next;
  207.         }
  208.         //TODO: switch to another CPU, synched with kcpulb,
  209.     }
  210.     spinlock_unlock(&tasklet_lock);
  211. }
  212.  
  213. /** Frees the tasklet structure when no longer needed
  214. * @param tasklet to be freed
  215. */
  216. void tasklet_free(tasklet_descriptor_t* t)
  217. {
  218.     if (t->state == TASKLET_STATE_NOTACTIVE)
  219.         free(t);
  220.     else
  221.         panic_printf("attempting to free an active tasklet");
  222. }
  223.  
  224.  
  225.