root / Whitix / branches / hybrid / kernel / timer.c

Revision 537, 3.6 kB (checked in by mwhitworth, 5 months ago)

Simplify timer code.

Line 
1/*  This file is part of Whitix.
2 *
3 *  Whitix is free software; you can redistribute it and/or modify
4 *  it under the terms of the GNU General Public License as published by
5 *  the Free Software Foundation; either version 2 of the License, or
6 *  (at your option) any later version.
7 *
8 *  Whitix is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 *  GNU General Public License for more details.
12 *
13 *  You should have received a copy of the GNU General Public License
14 *  along with Whitix; if not, write to the Free Software
15 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16 *
17 */
18
19#include <timer.h>
20#include <llist.h>
21#include <console.h>
22#include <module.h>
23#include <error.h>
24#include <task.h>
25#include <malloc.h>
26
27LIST_HEAD(timerList);
28Spinlock timerLock;
29
30/***********************************************************************
31 *
32 * FUNCTION: TimerAdd
33 *
34 * DESCRIPTION: Add a timer to the list.
35 *
36 * PARAMETERS: timer - timer in question.
37 *
38 * RETURNS: Usual error codes.
39 *
40 ***********************************************************************/
41
42void TimerAdd(struct Timer* timer)
43{
44        SpinLockIrq(&timerLock);
45        struct Timer* curr;
46
47        if (ListEmpty(&timerList))
48                ListAdd(&timer->list,&timerList);
49        else{
50                ListForEachEntry(curr,&timerList,list)
51                {
52                        if (curr->expires > timer->expires)
53                        {
54                                if (curr->list.prev != &timerList)
55                                        timer->expires-=ListEntry(curr->list.prev,struct Timer,list)->expires;
56
57                                curr->expires-=timer->expires;
58
59                                /* Add before the current timer. */
60                                DoListAdd(&timer->list,curr->list.prev,&curr->list);
61                                goto out;
62                        }
63                }
64
65                /* Add to end of list */
66                if (curr->list.prev != &timerList)
67                        timer->expires-=ListEntry(curr->list.prev,struct Timer,list)->expires;
68
69                ListAddTail(&timer->list,&timerList);
70        }
71
72out:
73        SpinUnlockIrq(&timerLock);
74}
75
76SYMBOL_EXPORT(TimerAdd);
77
78/***********************************************************************
79 *
80 * FUNCTION: TimerRemove
81 *
82 * DESCRIPTION: Remove a timer and update other timers.
83 *
84 * PARAMETERS: timer - timer in question.
85 *
86 * RETURNS: Usual error codes.
87 *
88 ***********************************************************************/
89
90int TimerRemove(struct Timer* timer)
91{
92        int err=0;
93        SpinLockIrq(&timerLock);
94
95        if (ListEmpty(&timerList))
96                err=-EINVAL;
97        else{
98                struct Timer* curr,*curr2;
99                ListForEachEntrySafe(curr,curr2,&timerList,list)
100                {
101                        if (curr == timer)
102                        {
103                                ListRemove(&curr->list);
104
105                                if (timer->expires > 0)
106                                        curr2->expires+=curr->expires;
107                        }
108                }
109        }
110
111        SpinUnlockIrq(&timerLock);
112
113        return err;
114}
115
116SYMBOL_EXPORT(TimerRemove);
117
118/***********************************************************************
119 *
120 * FUNCTION: UpdateTimers
121 *
122 * DESCRIPTION: Update the list of timers.
123 *
124 * PARAMETERS: None.
125 *
126 * RETURNS: Nothing.
127 *
128 ***********************************************************************/
129
130/* TODO: Does it really need to run in an IRQ? */
131
132void UpdateTimers()
133{
134        struct Timer* timer;
135
136        if (ListEmpty(&timerList))
137                return;
138
139        /* Get head of the list */
140        timer=ListEntry(timerList.next,struct Timer,list);
141        timer->expires-=10; /* The timeslice */
142
143        if (timer->expires <= 0)
144        {
145                ListRemove(&timer->list);
146                timer->func(timer->data);
147        }
148}
149
150static void SleepWakeup(void* data)
151{
152        struct Thread* thread=(struct Thread*)data;
153        ThrStartThread(thread);
154}
155
156void Sleep(int milliSeconds)
157{
158        struct Timer timer;
159
160        timer.func=SleepWakeup;
161        timer.expires=milliSeconds;
162        timer.data=currThread;
163
164        TimerAdd(&timer);
165        ThrSuspendThread(currThread);
166        ThrSchedule();
167}
168
169SYMBOL_EXPORT(Sleep);
Note: See TracBrowser for help on using the browser.