Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
2260 hudecek 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