Subversion Repositories HelenOS

Rev

Rev 2330 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2330 Rev 2430
Line 28... Line 28...
28
 */
28
 */
29
 
29
 
30
/** @addtogroup genericddi
30
/** @addtogroup genericddi
31
 * @{
31
 * @{
32
 */
32
 */
33
/** @file
33
/** @file tasklet.c
-
 
34
 *  @brief Tasklet implementation
34
 */
35
 */
35
 
36
 
36
#include <arch.h>
37
#include <arch.h>
37
#include <config.h>
38
#include <config.h>
38
#include <arch/types.h>
39
#include <arch/types.h>
Line 89... Line 90...
89
void tasklet_run_tasklet_thread(task_t * kernel_task)
90
void tasklet_run_tasklet_thread(task_t * kernel_task)
90
{
91
{
91
    //create the tasklet_thread, it's wired to the current cpu, we'll migrate it ourselves
92
    //create the tasklet_thread, it's wired to the current cpu, we'll migrate it ourselves
92
    thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, THREAD_FLAG_WIRED, "tasklet_thread", false);
93
    thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, THREAD_FLAG_WIRED, "tasklet_thread", false);
93
    if (t==NULL) {
94
    if (t==NULL) {
94
        //wtf?
-
 
95
        panic_printf("tasklet thread not created\n");
95
        panic_printf("tasklet thread not created\n");
96
    } else {
96
    } else {
97
        spinlock_lock(&t->lock);           
97
        spinlock_lock(&t->lock);   
-
 
98
        //we'll default on the first CPU
98
        t->cpu = &cpus[0];
99
        t->cpu = &cpus[0];
99
        t->priority = TASKLET_THREAD_PRIORITY;
100
        t->priority = TASKLET_THREAD_PRIORITY;
100
        spinlock_unlock(&t->lock);
101
        spinlock_unlock(&t->lock);
101
        thread_ready(t);
102
        thread_ready(t);
102
    }
103
    }
Line 112... Line 113...
112
    cpu_t *cpu;
113
    cpu_t *cpu;
113
#endif
114
#endif
114
    waitq_t  wq;
115
    waitq_t  wq;
115
    waitq_initialize(&wq);
116
    waitq_initialize(&wq);
116
   
117
   
-
 
118
    //the infinite loop
117
    while (true) {
119
    while (true) {
-
 
120
        //execute any scheduled tasklets
118
        tasklet_do();
121
        tasklet_do();
119
#ifdef CONFIG_SMP
122
#ifdef CONFIG_SMP
-
 
123
        //check whether other CPUs have tasklets to execute
120
        if (config.cpu_active>1) {
124
        if (config.cpu_active>1) {
121
            current_cpu = CPU->id;
125
            current_cpu = CPU->id;
122
            //find the first cpu with nonempty tasklet_list 
126
            //find the first cpu with nonempty tasklet_list 
123
            for (new_cpu = (current_cpu + 1) % config.cpu_active; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 && cpus[new_cpu].active;
127
            for (new_cpu = (current_cpu + 1) % config.cpu_count; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 ;
124
                    new_cpu=(new_cpu + 1)% config.cpu_active);
128
                    new_cpu=(new_cpu + 1)% config.cpu_count);
125
 
129
 
-
 
130
            //if we found a CPU with unsatisfied tasklet schedule to run there. It must be active!
126
            if (new_cpu!=current_cpu) {
131
            if (new_cpu!=current_cpu && cpus[new_cpu].active) {
127
                //we need to migrate this thread to CPU with id new_cpu
132
                //we need to migrate this thread to CPU with id new_cpu
128
                cpu = &cpus[new_cpu];
133
                cpu = &cpus[new_cpu];
129
 
134
 
130
                spinlock_lock(&THREAD->lock);
135
                spinlock_lock(&THREAD->lock);
131
                //put tasklet_thread on the new_cpu 
136
                //move tasklet_thread on the new_cpu 
132
                THREAD->cpu = cpu;
137
                THREAD->cpu = cpu;
133
                spinlock_unlock(&THREAD->lock);
138
                spinlock_unlock(&THREAD->lock);
134
            }
139
            }
135
        }
140
        }
136
#endif
141
#endif
Line 201... Line 206...
201
}
206
}
202
 
207
 
203
 
208
 
204
 
209
 
205
 
210
 
206
/** Executes scheduled enabled tasklets on current CPU */
211
/** Executes scheduled enabled tasklets on current CPU
-
 
212
* this function could be called from other parts of kernel */
207
void tasklet_do(void)
213
void tasklet_do(void)
208
{
214
{
209
    spinlock_lock(&tasklet_lock);
215
    spinlock_lock(&tasklet_lock);
210
    tasklet_descriptor_t* t = tasklet_list[CPU->id];
216
    tasklet_descriptor_t* t = tasklet_list[CPU->id];
211
    //printf(".");
-
 
212
    if (t) {
217
    if (t) {
213
        //empty the tasklet_list
218
        //empty the tasklet_list
214
        tasklet_list[CPU->id]=0;
219
        tasklet_list[CPU->id]=0;
215
        spinlock_unlock(&tasklet_lock);
220
        spinlock_unlock(&tasklet_lock);
216
        do {
221
        do {
217
            if (!(t->state & TASKLET_STATE_DISABLED)) {
222
            if (!(t->state & TASKLET_STATE_DISABLED)) {
218
                if (t->func) {
223
                if (t->func) {
219
                    t->state = TASKLET_STATE_RUNNING;
224
                    t->state = TASKLET_STATE_RUNNING;
220
                    t->func(t->data);
225
                    t->func(t->data);
221
                    //clear running flag, set not active - the tasklet can disable itself
226
                    //clear running flag, set not active 
222
                    //thats why we don't just set it as not active
-
 
223
                    t->state &= ~TASKLET_STATE_RUNNING;
227
                    t->state &= ~TASKLET_STATE_RUNNING;
224
                    t->state |= TASKLET_STATE_NOTACTIVE;
228
                    t->state |= TASKLET_STATE_NOTACTIVE;
225
                } else
229
                } else
226
                    panic_printf("tasklet func NULL\n");
230
                    panic_printf("tasklet func NULL\n");
227
            } else {  
231
            } else {  
Line 238... Line 242...
238
    else
242
    else
239
        spinlock_unlock(&tasklet_lock);
243
        spinlock_unlock(&tasklet_lock);
240
}
244
}
241
 
245
 
242
/** Frees the tasklet structure when no longer needed. The function doesn't provide
246
/** Frees the tasklet structure when no longer needed. The function doesn't provide
243
*   any synchronization, the caller must be sure, the tasklet is not scheduled.
247
*   any synchronization, the caller must be sure, that the tasklet is not scheduled.
244
*
248
*
245
* @param tasklet to be freed
249
* @param tasklet to be freed
246
*/
250
*/
247
void tasklet_free(tasklet_descriptor_t* t)
251
void tasklet_free(tasklet_descriptor_t* t)
248
{
252
{