Commit 467931d9b79e3122aacb1fe4270b32963a41886d
authorSami Liedes <sliedes@cc.hut.fi>
Fri, 4 Feb 2011 22:26:54 +0000 (00:26 +0200)
committerSami Liedes <sliedes@cc.hut.fi>
Fri, 4 Feb 2011 22:38:54 +0000 (00:38 +0200)
This optimization speeds up avr_cycle_timer_process() considerably. It
used to be a major bottleneck in my test case (52% of CPU time spent
in that routine), now it's about half that.

simavr/sim/sim_cycle_timers.c

index fed6b6c1ae6fe1b97d4b2913111b5206019ea63d..57fd0586f81ef2e8ad7a3d8c76ac5c2fb68eddf0 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <strings.h>
 #include "sim_cycle_timers.h"
 
 void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void * param)
@@ -70,15 +71,16 @@ void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param)
 avr_cycle_count_t
 avr_cycle_timer_status(avr_t * avr, avr_cycle_timer_t timer, void * param)
 {
-       if (!avr->cycle_timer_map)
-               return 0;
+       uint32_t map = avr->cycle_timer_map;
 
-       for (int i = 0; i < 32; i++)
-               if ((avr->cycle_timer_map & (1 << i)) &&
-                               avr->cycle_timer[i].timer == timer &&
-                               avr->cycle_timer[i].param == param) {
-                       return 1 + (avr->cycle_timer[i].when - avr->cycle);
+       while (map) {
+               int bit = ffs(map)-1;
+               if (avr->cycle_timer[bit].timer == timer &&
+                   avr->cycle_timer[bit].param == param) {
+                       return 1 + (avr->cycle_timer[bit].when - avr->cycle);
                }
+               map &= ~(1 << bit);
+       }
 
        return 0;
 }
@@ -94,28 +96,29 @@ avr_cycle_count_t avr_cycle_timer_process(avr_t * avr)
                return (avr_cycle_count_t)-1;
 
        avr_cycle_count_t min = (avr_cycle_count_t)-1;
+       uint32_t map = avr->cycle_timer_map;
 
-       for (int i = 0; i < 32; i++) {
-               if (!(avr->cycle_timer_map & (1 << i)))
-                       continue;
+       while (map) {
+               int bit = ffs(map)-1;
                // do it several times, in case we're late
-               while (avr->cycle_timer[i].when && avr->cycle_timer[i].when <= avr->cycle) {
+               while (avr->cycle_timer[bit].when && avr->cycle_timer[bit].when <= avr->cycle) {
                        // call it
-                       avr->cycle_timer[i].when =
-                                       avr->cycle_timer[i].timer(avr,
-                                                       avr->cycle_timer[i].when,
-                                                       avr->cycle_timer[i].param);
-                       if (avr->cycle_timer[i].when == 0) {
+                       avr->cycle_timer[bit].when =
+                                       avr->cycle_timer[bit].timer(avr,
+                                                       avr->cycle_timer[bit].when,
+                                                       avr->cycle_timer[bit].param);
+                       if (avr->cycle_timer[bit].when == 0) {
                                // clear it
-                               avr->cycle_timer[i].timer = NULL;
-                               avr->cycle_timer[i].param = NULL;
-                               avr->cycle_timer[i].when = 0;
-                               avr->cycle_timer_map &= ~(1 << i);
+                               avr->cycle_timer[bit].timer = NULL;
+                               avr->cycle_timer[bit].param = NULL;
+                               avr->cycle_timer[bit].when = 0;
+                               avr->cycle_timer_map &= ~(1 << bit);
                                break;
                        }
                }
-               if (avr->cycle_timer[i].when && avr->cycle_timer[i].when < min)
-                       min = avr->cycle_timer[i].when;
+               if (avr->cycle_timer[bit].when && avr->cycle_timer[bit].when < min)
+                       min = avr->cycle_timer[bit].when;
+               map &= ~(1 << bit);             
        }
        return min - avr->cycle;
 }