Changes BITMASK_FOR_EACH to a macro
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 7 Jan 2013 23:36:14 +0000 (15:36 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 7 Jan 2013 23:36:14 +0000 (15:36 -0800)
Need this to avoid needlessly taking the address of the function being
executed on each bit.  Helps with performance, esp on RISCV.

kern/include/bitmask.h
user/parlib/include/bitmask.h

index 26b5107..a3433a4 100644 (file)
@@ -36,17 +36,22 @@ static inline void CLR_BITMASK_RANGE(uint8_t* m, size_t beg, size_t end)
 }
 
 /* Runs *work on every bit in the bitmask, passing *work the value of the bit
- * that is set.  Optionally clears the bit from the bitmask */
-static void BITMASK_FOREACH_SET(uint8_t *name, unsigned int size,
-                                void (*work)(unsigned int bit), bool clear)
-{
-       for (int i = 0; i < size; i++) {
-               bool present = GET_BITMASK_BIT(name, i);
-               if (present && clear)
-                       CLR_BITMASK_BIT_ATOMIC(name, i);
-               if (present)
-                       work(i);
-       }
-}
+ * that is set.  Optionally clears the bit from the bitmask. 
+ *
+ * We need this to be a macro, so that the calling code doesn't need the
+ * address for work_fn.  This matters for code that has nested functions that
+ * use local variables, since taking the address of work_fn will force the
+ * compiler to put the function on the stack and incur icache coherency
+ * overheads. */
+#define BITMASK_FOREACH_SET(name, size, work_fn, clear)                        \
+{                                                                              \
+       for (int i = 0; i < (size); i++) {                                         \
+               bool present = GET_BITMASK_BIT((name), i);                             \
+               if (present && (clear))                                                \
+                       CLR_BITMASK_BIT_ATOMIC((name), i);                                 \
+               if (present)                                                           \
+                       (work_fn)(i);                                                      \
+       }                                                                          \
+}                                                                              
 
 #endif /* ROS_KERN_BITMASK_H */
index 668ef19..e3aee31 100644 (file)
@@ -36,17 +36,22 @@ static inline void CLR_BITMASK_RANGE(uint8_t* m, size_t beg, size_t end)
 }
 
 /* Runs *work on every bit in the bitmask, passing *work the value of the bit
- * that is set.  Optionally clears the bit from the bitmask */
-static void BITMASK_FOREACH_SET(uint8_t *name, unsigned int size,
-                                void (*work)(unsigned int bit), bool clear)
-{
-       for (int i = 0; i < size; i++) {
-               bool present = GET_BITMASK_BIT(name, i);
-               if (present && clear)
-                       CLR_BITMASK_BIT_ATOMIC(name, i);
-               if (present)
-                       work(i);
-       }
-}
-
+ * that is set.  Optionally clears the bit from the bitmask. 
+ *
+ * We need this to be a macro, so that the calling code doesn't need the
+ * address for work_fn.  This matters for code that has nested functions that
+ * use local variables, since taking the address of work_fn will force the
+ * compiler to put the function on the stack and incur icache coherency
+ * overheads. */
+#define BITMASK_FOREACH_SET(name, size, work_fn, clear)                        \
+{                                                                              \
+       for (int i = 0; i < (size); i++) {                                         \
+               bool present = GET_BITMASK_BIT((name), i);                             \
+               if (present && (clear))                                                \
+                       CLR_BITMASK_BIT_ATOMIC((name), i);                                 \
+               if (present)                                                           \
+                       (work_fn)(i);                                                      \
+       }                                                                          \
+}                                                                              
+                                                                               
 #endif /* PARLIB_BITMASK_H */