53 |
|
struct TMDesc { |
54 |
|
uint32 task; // Mac address of associated TMTask |
55 |
|
tm_time_t wakeup; // Time this task is scheduled for execution |
56 |
< |
bool in_use; // Flag: descriptor in use |
56 |
> |
TMDesc *next; |
57 |
|
}; |
58 |
|
|
59 |
< |
const int NUM_DESCS = 64; // Maximum number of descriptors |
60 |
< |
static TMDesc desc[NUM_DESCS]; |
59 |
> |
static TMDesc *tmDescList; |
60 |
|
|
61 |
|
#if PRECISE_TIMING |
62 |
|
#ifdef PRECISE_TIMING_BEOS |
88 |
|
#endif |
89 |
|
|
90 |
|
|
91 |
< |
/* |
93 |
< |
* Allocate descriptor for given TMTask in list |
94 |
< |
*/ |
95 |
< |
|
96 |
< |
static int alloc_desc(uint32 tm) |
91 |
> |
inline static void free_desc(TMDesc *desc) |
92 |
|
{ |
93 |
< |
// Search for first free descriptor |
94 |
< |
for (int i=0; i<NUM_DESCS; i++) |
95 |
< |
if (!desc[i].in_use) { |
96 |
< |
desc[i].task = tm; |
97 |
< |
desc[i].in_use = true; |
98 |
< |
return i; |
93 |
> |
if (desc == tmDescList) { |
94 |
> |
tmDescList = desc->next; |
95 |
> |
} else { |
96 |
> |
for (TMDesc *d = tmDescList; d; d = d->next) { |
97 |
> |
if (d->next == desc) { |
98 |
> |
d->next = desc->next; |
99 |
> |
break; |
100 |
> |
} |
101 |
|
} |
102 |
< |
return -1; |
103 |
< |
} |
107 |
< |
|
108 |
< |
|
109 |
< |
/* |
110 |
< |
* Free descriptor in list |
111 |
< |
*/ |
112 |
< |
|
113 |
< |
inline static void free_desc(int i) |
114 |
< |
{ |
115 |
< |
desc[i].in_use = false; |
102 |
> |
} |
103 |
> |
delete desc; |
104 |
|
} |
105 |
|
|
118 |
– |
|
106 |
|
/* |
107 |
|
* Find descriptor associated with given TMTask |
108 |
|
*/ |
109 |
|
|
110 |
< |
inline static int find_desc(uint32 tm) |
110 |
> |
inline static TMDesc *find_desc(uint32 tm) |
111 |
|
{ |
112 |
< |
for (int i=0; i<NUM_DESCS; i++) |
113 |
< |
if (desc[i].in_use && desc[i].task == tm) |
114 |
< |
return i; |
115 |
< |
return -1; |
112 |
> |
TMDesc *desc = tmDescList; |
113 |
> |
while (desc) { |
114 |
> |
if (desc->task == tm) { |
115 |
> |
return desc; |
116 |
> |
} |
117 |
> |
desc = desc->next; |
118 |
> |
} |
119 |
> |
return NULL; |
120 |
|
} |
121 |
|
|
122 |
|
|
262 |
|
|
263 |
|
void TimerInit(void) |
264 |
|
{ |
265 |
< |
// Mark all descriptors as inactive |
275 |
< |
for (int i=0; i<NUM_DESCS; i++) |
276 |
< |
free_desc(i); |
265 |
> |
TimerReset(); |
266 |
|
|
267 |
|
#if PRECISE_TIMING |
268 |
|
// Start timer thread |
320 |
|
|
321 |
|
void TimerReset(void) |
322 |
|
{ |
323 |
< |
// Mark all descriptors as inactive |
324 |
< |
for (int i=0; i<NUM_DESCS; i++) |
325 |
< |
free_desc(i); |
323 |
> |
TMDesc *desc = tmDescList; |
324 |
> |
while (desc) { |
325 |
> |
TMDesc *next = desc->next; |
326 |
> |
delete desc; |
327 |
> |
desc = desc->next; |
328 |
> |
} |
329 |
> |
tmDescList = NULL; |
330 |
|
} |
331 |
|
|
332 |
|
|
338 |
|
{ |
339 |
|
D(bug("InsTime %08lx, trap %04x\n", tm, trap)); |
340 |
|
WriteMacInt16((uint32)tm + qType, ReadMacInt16((uint32)tm + qType) & 0x1fff | (trap << 4) & 0x6000); |
341 |
< |
if (find_desc(tm) >= 0) |
342 |
< |
printf("WARNING: InsTime(): Task re-inserted\n"); |
341 |
> |
if (find_desc(tm)) |
342 |
> |
printf("WARNING: InsTime(%08lx): Task re-inserted\n", tm); |
343 |
|
else { |
344 |
< |
int i = alloc_desc(tm); |
345 |
< |
if (i < 0) |
346 |
< |
printf("FATAL: InsTime(): No free Time Manager descriptor\n"); |
344 |
> |
TMDesc *desc = new TMDesc; |
345 |
> |
desc->task = tm; |
346 |
> |
desc->next = tmDescList; |
347 |
> |
tmDescList = desc; |
348 |
|
} |
349 |
|
return 0; |
350 |
|
} |
359 |
|
D(bug("RmvTime %08lx\n", tm)); |
360 |
|
|
361 |
|
// Find descriptor |
362 |
< |
int i = find_desc(tm); |
363 |
< |
if (i < 0) { |
362 |
> |
TMDesc *desc = find_desc(tm); |
363 |
> |
if (!desc) { |
364 |
|
printf("WARNING: RmvTime(%08lx): Descriptor not found\n", tm); |
365 |
|
return 0; |
366 |
|
} |
386 |
|
#if PRECISE_TIMING |
387 |
|
// Look for next task to be called and set wakeup_time |
388 |
|
wakeup_time = wakeup_time_max; |
389 |
< |
for (int j=0; j<NUM_DESCS; j++) { |
390 |
< |
if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000)) |
391 |
< |
if (timer_cmp_time(desc[j].wakeup, wakeup_time) < 0) |
392 |
< |
wakeup_time = desc[j].wakeup; |
399 |
< |
} |
389 |
> |
for (TMDesc *d = tmDescList; d; d = d->next) |
390 |
> |
if ((ReadMacInt16(d->task + qType) & 0x8000)) |
391 |
> |
if (timer_cmp_time(d->wakeup, wakeup_time) < 0) |
392 |
> |
wakeup_time = d->wakeup; |
393 |
|
#endif |
394 |
|
|
395 |
|
// Compute remaining time |
396 |
|
tm_time_t remaining, current; |
397 |
|
timer_current_time(current); |
398 |
< |
timer_sub_time(remaining, desc[i].wakeup, current); |
398 |
> |
timer_sub_time(remaining, desc->wakeup, current); |
399 |
|
WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining)); |
400 |
|
} else |
401 |
|
WriteMacInt32(tm + tmCount, 0); |
420 |
|
#endif |
421 |
|
|
422 |
|
// Free descriptor |
423 |
< |
free_desc(i); |
423 |
> |
free_desc(desc); |
424 |
|
return 0; |
425 |
|
} |
426 |
|
|
434 |
|
D(bug("PrimeTime %08lx, time %ld\n", tm, time)); |
435 |
|
|
436 |
|
// Find descriptor |
437 |
< |
int i = find_desc(tm); |
438 |
< |
if (i < 0) { |
439 |
< |
printf("FATAL: PrimeTime(): Descriptor not found\n"); |
437 |
> |
TMDesc *desc = find_desc(tm); |
438 |
> |
if (!desc) { |
439 |
> |
printf("FATAL: PrimeTime(%08lx): Descriptor not found\n", tm); |
440 |
|
return 0; |
441 |
|
} |
442 |
|
|
460 |
|
|
461 |
|
// Yes, calculate wakeup time relative to last scheduled time |
462 |
|
tm_time_t wakeup; |
463 |
< |
timer_add_time(wakeup, desc[i].wakeup, delay); |
464 |
< |
desc[i].wakeup = wakeup; |
463 |
> |
timer_add_time(wakeup, desc->wakeup, delay); |
464 |
> |
desc->wakeup = wakeup; |
465 |
|
|
466 |
|
} else { |
467 |
|
|
468 |
|
// No, calculate wakeup time relative to current time |
469 |
|
tm_time_t now; |
470 |
|
timer_current_time(now); |
471 |
< |
timer_add_time(desc[i].wakeup, now, delay); |
471 |
> |
timer_add_time(desc->wakeup, now, delay); |
472 |
|
} |
473 |
|
|
474 |
|
// Set tmWakeUp to indicate that task was scheduled |
479 |
|
// Not extended task, calculate wakeup time relative to current time |
480 |
|
tm_time_t now; |
481 |
|
timer_current_time(now); |
482 |
< |
timer_add_time(desc[i].wakeup, now, delay); |
482 |
> |
timer_add_time(desc->wakeup, now, delay); |
483 |
|
} |
484 |
|
|
485 |
|
// Make task active and enqueue it in the Time Manager queue |
500 |
|
#if PRECISE_TIMING |
501 |
|
// Look for next task to be called and set wakeup_time |
502 |
|
wakeup_time = wakeup_time_max; |
503 |
< |
for (int j=0; j<NUM_DESCS; j++) { |
504 |
< |
if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000)) |
505 |
< |
if (timer_cmp_time(desc[j].wakeup, wakeup_time) < 0) |
506 |
< |
wakeup_time = desc[j].wakeup; |
514 |
< |
} |
503 |
> |
for (TMDesc *d = tmDescList; d; d = d->next) |
504 |
> |
if ((ReadMacInt16(d->task + qType) & 0x8000)) |
505 |
> |
if (timer_cmp_time(d->wakeup, wakeup_time) < 0) |
506 |
> |
wakeup_time = d->wakeup; |
507 |
|
#ifdef PRECISE_TIMING_BEOS |
508 |
|
release_sem(wakeup_time_sem); |
509 |
|
thread_info info; |
573 |
|
} |
574 |
|
semaphore_signal(wakeup_time_sem); |
575 |
|
} |
576 |
+ |
return NULL; |
577 |
|
} |
578 |
|
#endif |
579 |
|
|
612 |
|
// Look for active TMTasks that have expired |
613 |
|
tm_time_t now; |
614 |
|
timer_current_time(now); |
615 |
< |
for (int i=0; i<NUM_DESCS; i++) |
616 |
< |
if (desc[i].in_use) { |
617 |
< |
uint32 tm = desc[i].task; |
618 |
< |
if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc[i].wakeup, now) <= 0) { |
619 |
< |
|
620 |
< |
// Found one, mark as inactive and remove it from the Time Manager queue |
621 |
< |
WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); |
622 |
< |
dequeue_tm(tm); |
623 |
< |
|
624 |
< |
// Call timer function |
625 |
< |
uint32 addr = ReadMacInt32(tm + tmAddr); |
626 |
< |
if (addr) { |
627 |
< |
D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr)); |
628 |
< |
M68kRegisters r; |
629 |
< |
r.a[0] = addr; |
630 |
< |
r.a[1] = tm; |
631 |
< |
Execute68k(r.a[0], &r); |
632 |
< |
D(bug(" returned from TimeTask\n")); |
633 |
< |
} |
615 |
> |
TMDesc *desc = tmDescList; |
616 |
> |
while (desc) { |
617 |
> |
TMDesc *next = desc->next; |
618 |
> |
uint32 tm = desc->task; |
619 |
> |
if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc->wakeup, now) <= 0) { |
620 |
> |
|
621 |
> |
// Found one, mark as inactive and remove it from the Time Manager queue |
622 |
> |
WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); |
623 |
> |
dequeue_tm(tm); |
624 |
> |
|
625 |
> |
// Call timer function |
626 |
> |
uint32 addr = ReadMacInt32(tm + tmAddr); |
627 |
> |
if (addr) { |
628 |
> |
D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr)); |
629 |
> |
M68kRegisters r; |
630 |
> |
r.a[0] = addr; |
631 |
> |
r.a[1] = tm; |
632 |
> |
Execute68k(r.a[0], &r); |
633 |
> |
D(bug(" returned from TimeTask\n")); |
634 |
|
} |
635 |
|
} |
636 |
+ |
desc = next; |
637 |
+ |
} |
638 |
|
|
639 |
|
#if PRECISE_TIMING |
640 |
|
// Look for next task to be called and set wakeup_time |
651 |
|
pthread_mutex_lock(&wakeup_time_lock); |
652 |
|
#endif |
653 |
|
wakeup_time = wakeup_time_max; |
654 |
< |
for (int j=0; j<NUM_DESCS; j++) { |
655 |
< |
if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000)) |
656 |
< |
if (timer_cmp_time(desc[j].wakeup, wakeup_time) < 0) |
657 |
< |
wakeup_time = desc[j].wakeup; |
663 |
< |
} |
654 |
> |
for (TMDesc *d = tmDescList; d; d = d->next) |
655 |
> |
if ((ReadMacInt16(d->task + qType) & 0x8000)) |
656 |
> |
if (timer_cmp_time(d->wakeup, wakeup_time) < 0) |
657 |
> |
wakeup_time = d->wakeup; |
658 |
|
#if PRECISE_TIMING_BEOS |
659 |
|
release_sem(wakeup_time_sem); |
660 |
|
thread_info info; |