vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / drivers / network / ipro1000 / timer.c
blob2655b99c6ab6c721bce842a41cd0a99edce5ca6b
1 /* Intel PRO/1000 Family Driver
2 * Copyright (C) 2004 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
4 * Permission to use, copy, modify and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies, and that both the
7 * copyright notice and this permission notice appear in supporting documentation.
9 * Marcus Overhagen makes no representations about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
12 * MARCUS OVERHAGEN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL MARCUS
14 * OVERHAGEN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
15 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <Errors.h>
20 #include <OS.h>
21 #include <string.h>
23 #include "debug.h"
24 #include "timer.h"
26 #define MAX_TIMERS 4
29 struct timer_info
31 timer_id id;
32 timer_function func;
33 void * cookie;
34 bigtime_t next_event;
35 bigtime_t interval;
36 bool periodic;
40 static struct timer_info sTimerData[MAX_TIMERS];
41 static int sTimerCount;
42 static timer_id sTimerNextId;
43 static thread_id sTimerThread;
44 static sem_id sTimerSem;
45 static spinlock sTimerSpinlock;
48 static int32
49 timer_thread(void *cookie)
51 status_t status = 0;
53 do {
54 bigtime_t timeout;
55 bigtime_t now;
56 cpu_status cpu;
57 timer_function func;
58 void * cookie;
59 int i;
60 int index;
62 cpu = disable_interrupts();
63 acquire_spinlock(&sTimerSpinlock);
65 now = system_time();
66 cookie = 0;
67 func = 0;
69 // find timer with smallest event time
70 index = -1;
71 timeout = B_INFINITE_TIMEOUT;
72 for (i = 0; i < sTimerCount; i++) {
73 if (sTimerData[i].next_event < timeout) {
74 timeout = sTimerData[i].next_event;
75 index = i;
79 if (timeout < now) {
80 // timer is ready for execution, load func and cookie
81 ASSERT(index >= 0 && index < sTimerCount);
82 func = sTimerData[index].func;
83 cookie = sTimerData[index].cookie;
84 if (sTimerData[index].periodic) {
85 // periodic timer is ready, update the entry
86 sTimerData[index].next_event += sTimerData[index].interval;
87 } else {
88 // single shot timer is ready, delete the entry
89 if (index != (sTimerCount - 1) && sTimerCount != 1) {
90 memcpy(&sTimerData[index], &sTimerData[sTimerCount - 1], sizeof(struct timer_info));
92 sTimerCount--;
96 release_spinlock(&sTimerSpinlock);
97 restore_interrupts(cpu);
99 // execute timer hook
100 if (timeout < now) {
101 ASSERT(func);
102 func(cookie);
103 continue;
106 status = acquire_sem_etc(sTimerSem, 1, B_ABSOLUTE_TIMEOUT, timeout);
107 } while (status != B_BAD_SEM_ID);
109 return 0;
113 timer_id
114 create_timer(timer_function func, void *cookie, bigtime_t interval, uint32 flags)
116 cpu_status cpu;
117 timer_id id;
119 if (func == 0)
120 return -1;
122 // Attention: flags are not real flags, as B_PERIODIC_TIMER is 3
124 cpu = disable_interrupts();
125 acquire_spinlock(&sTimerSpinlock);
127 if (sTimerCount < MAX_TIMERS) {
128 id = sTimerNextId;
129 sTimerData[sTimerCount].id = id;
130 sTimerData[sTimerCount].func = func;
131 sTimerData[sTimerCount].cookie = cookie;
132 sTimerData[sTimerCount].next_event = (flags == B_ONE_SHOT_ABSOLUTE_TIMER) ? interval : system_time() + interval;
133 sTimerData[sTimerCount].interval = interval;
134 sTimerData[sTimerCount].periodic = flags == B_PERIODIC_TIMER;
135 sTimerNextId++;
136 sTimerCount++;
137 } else {
138 id = -1;
141 release_spinlock(&sTimerSpinlock);
142 restore_interrupts(cpu);
144 if (id != -1)
145 release_sem_etc(sTimerSem, 1, B_DO_NOT_RESCHEDULE);
147 return id;
151 status_t
152 delete_timer(timer_id id)
154 cpu_status cpu;
155 bool deleted;
156 int i;
158 deleted = false;
160 cpu = disable_interrupts();
161 acquire_spinlock(&sTimerSpinlock);
163 for (i = 0; i < sTimerCount; i++) {
164 if (sTimerData[i].id == id) {
165 if (i != (sTimerCount - 1) && sTimerCount != 1) {
166 memcpy(&sTimerData[i], &sTimerData[sTimerCount - 1], sizeof(struct timer_info));
168 sTimerCount--;
169 deleted = true;
170 break;
174 release_spinlock(&sTimerSpinlock);
175 restore_interrupts(cpu);
177 if (!deleted)
178 return B_ERROR;
180 release_sem_etc(sTimerSem, 1, B_DO_NOT_RESCHEDULE);
181 return B_OK;
185 status_t
186 initialize_timer(void)
188 sTimerCount = 0;
189 sTimerNextId = 1;
190 sTimerSpinlock = 0;
192 sTimerThread = spawn_kernel_thread(timer_thread, "ipro1000 timer", 80, 0);
193 sTimerSem = create_sem(0, "ipro1000 timer");
194 set_sem_owner(sTimerSem, B_SYSTEM_TEAM);
196 if (sTimerSem < 0 || sTimerThread < 0) {
197 delete_sem(sTimerSem);
198 kill_thread(sTimerThread);
199 return B_ERROR;
202 resume_thread(sTimerThread);
203 return B_OK;
207 status_t
208 terminate_timer(void)
210 status_t thread_return_value;
212 delete_sem(sTimerSem);
213 return wait_for_thread(sTimerThread, &thread_return_value);