1/*- 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 22 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * From: @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 |
39 * $FreeBSD: head/sys/kern/kern_timeout.c 72200 2001-02-09 06:11:45Z bmilekic $ |
40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/callout.h> 45#include <sys/kernel.h> 46#include <sys/mutex.h> 47 --- 38 unchanged lines hidden (view full) --- 86 register int steps; /* #steps since we last allowed interrupts */ 87 88#ifndef MAX_SOFTCLOCK_STEPS 89#define MAX_SOFTCLOCK_STEPS 100 /* Maximum allowed value of steps. */ 90#endif /* MAX_SOFTCLOCK_STEPS */ 91 92 steps = 0; 93 s = splhigh(); |
94 mtx_lock_spin(&callout_lock); |
95 while (softticks != ticks) { 96 softticks++; 97 /* 98 * softticks may be modified by hard clock, so cache 99 * it while we work on a given bucket. 100 */ 101 curticks = softticks; 102 bucket = &callwheel[curticks & callwheelmask]; 103 c = TAILQ_FIRST(bucket); 104 while (c) { 105 if (c->c_time != curticks) { 106 c = TAILQ_NEXT(c, c_links.tqe); 107 ++steps; 108 if (steps >= MAX_SOFTCLOCK_STEPS) { 109 nextsoftcheck = c; 110 /* Give interrupts a chance. */ |
111 mtx_unlock_spin(&callout_lock); |
112 splx(s); 113 s = splhigh(); |
114 mtx_lock_spin(&callout_lock); |
115 c = nextsoftcheck; 116 steps = 0; 117 } 118 } else { 119 void (*c_func)(void *); 120 void *c_arg; 121 int c_flags; 122 --- 6 unchanged lines hidden (view full) --- 129 if (c->c_flags & CALLOUT_LOCAL_ALLOC) { 130 c->c_flags = CALLOUT_LOCAL_ALLOC; 131 SLIST_INSERT_HEAD(&callfree, c, 132 c_links.sle); 133 } else { 134 c->c_flags = 135 (c->c_flags & ~CALLOUT_PENDING); 136 } |
137 mtx_unlock_spin(&callout_lock); |
138 if (!(c_flags & CALLOUT_MPSAFE)) |
139 mtx_lock(&Giant); |
140 splx(s); 141 c_func(c_arg); 142 s = splhigh(); 143 if (!(c_flags & CALLOUT_MPSAFE)) |
144 mtx_unlock(&Giant); 145 mtx_lock_spin(&callout_lock); |
146 steps = 0; 147 c = nextsoftcheck; 148 } 149 } 150 } 151 nextsoftcheck = NULL; |
152 mtx_unlock_spin(&callout_lock); |
153 splx(s); 154} 155 156/* 157 * timeout -- 158 * Execute a function after a specified length of time. 159 * 160 * untimeout -- --- 14 unchanged lines hidden (view full) --- 175 void *arg; 176 int to_ticks; 177{ 178 int s; 179 struct callout *new; 180 struct callout_handle handle; 181 182 s = splhigh(); |
183 mtx_lock_spin(&callout_lock); |
184 185 /* Fill in the next free callout structure. */ 186 new = SLIST_FIRST(&callfree); 187 if (new == NULL) 188 /* XXX Attempt to malloc first */ 189 panic("timeout table full"); 190 SLIST_REMOVE_HEAD(&callfree, c_links.sle); 191 192 callout_reset(new, to_ticks, ftn, arg); 193 194 handle.callout = new; |
195 mtx_unlock_spin(&callout_lock); |
196 splx(s); 197 return (handle); 198} 199 200void 201untimeout(ftn, arg, handle) 202 timeout_t *ftn; 203 void *arg; --- 5 unchanged lines hidden (view full) --- 209 * Check for a handle that was initialized 210 * by callout_handle_init, but never used 211 * for a real timeout. 212 */ 213 if (handle.callout == NULL) 214 return; 215 216 s = splhigh(); |
217 mtx_lock_spin(&callout_lock); |
218 if (handle.callout->c_func == ftn && handle.callout->c_arg == arg) 219 callout_stop(handle.callout); |
220 mtx_unlock_spin(&callout_lock); |
221 splx(s); 222} 223 224void 225callout_handle_init(struct callout_handle *handle) 226{ 227 handle->callout = NULL; 228} --- 17 unchanged lines hidden (view full) --- 246 struct callout *c; 247 int to_ticks; 248 void (*ftn) __P((void *)); 249 void *arg; 250{ 251 int s; 252 253 s = splhigh(); |
254 mtx_lock_spin(&callout_lock); |
255 if (c->c_flags & CALLOUT_PENDING) 256 callout_stop(c); 257 258 /* 259 * We could spl down here and back up at the TAILQ_INSERT_TAIL, 260 * but there's no point since doing this setup doesn't take much 261 * time. 262 */ 263 if (to_ticks <= 0) 264 to_ticks = 1; 265 266 c->c_arg = arg; 267 c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING); 268 c->c_func = ftn; 269 c->c_time = ticks + to_ticks; 270 TAILQ_INSERT_TAIL(&callwheel[c->c_time & callwheelmask], 271 c, c_links.tqe); |
272 mtx_unlock_spin(&callout_lock); |
273 splx(s); 274} 275 276void 277callout_stop(c) 278 struct callout *c; 279{ 280 int s; 281 282 s = splhigh(); |
283 mtx_lock_spin(&callout_lock); |
284 /* 285 * Don't attempt to delete a callout that's not on the queue. 286 */ 287 if (!(c->c_flags & CALLOUT_PENDING)) { 288 c->c_flags &= ~CALLOUT_ACTIVE; |
289 mtx_unlock_spin(&callout_lock); |
290 splx(s); 291 return; 292 } 293 c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING); 294 295 if (nextsoftcheck == c) { 296 nextsoftcheck = TAILQ_NEXT(c, c_links.tqe); 297 } 298 TAILQ_REMOVE(&callwheel[c->c_time & callwheelmask], c, c_links.tqe); 299 c->c_func = NULL; 300 301 if (c->c_flags & CALLOUT_LOCAL_ALLOC) { 302 SLIST_INSERT_HEAD(&callfree, c, c_links.sle); 303 } |
304 mtx_unlock_spin(&callout_lock); |
305 splx(s); 306} 307 308void 309callout_init(c, mpsafe) 310 struct callout *c; 311 int mpsafe; 312{ --- 48 unchanged lines hidden (view full) --- 361 362 /* 363 * Now rip through the timer calltodo list looking for timers 364 * to expire. 365 */ 366 367 /* don't collide with softclock() */ 368 s = splhigh(); |
369 mtx_lock_spin(&callout_lock); |
370 for (p = calltodo.c_next; p != NULL; p = p->c_next) { 371 p->c_time -= delta_ticks; 372 373 /* Break if the timer had more time on it than delta_ticks */ 374 if (p->c_time > 0) 375 break; 376 377 /* take back the ticks the timer didn't use (p->c_time <= 0) */ 378 delta_ticks = -p->c_time; 379 } |
380 mtx_unlock_spin(&callout_lock); |
381 splx(s); 382 383 return; 384} 385#endif /* APM_FIXUP_CALLTODO */ |