Use a constructor in benchutil/alarm
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Aug 2016 20:50:39 +0000 (16:50 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Aug 2016 21:35:14 +0000 (17:35 -0400)
It's possible to race with multiple threads (or vcore context) setting up
awaiters at the same time.  The nicer approach, and one that avoids a lot
of work in vcore context, is to use a constructor.

Programs that *might* call the alarm code (thus link and trigger the
constructor) will pay the setup tax (opening FDs, etc), instead of delaying
that setup cost until when we *know* they will use the alarms.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/benchutil/alarm.c

index 612c35a..17bf7b4 100644 (file)
@@ -14,7 +14,7 @@
  * Your handlers will run from vcore context.
  *
  * Code differences from the kernel (for future porting):
- * - init_alarm_service, run once out of init_awaiter (or wherever).
+ * - init_alarm_service, run as a constructor
  * - set_alarm() and friends are __tc_set_alarm(), passing global_tchain.
  * - reset_tchain_interrupt() uses #alarm
  * - removed anything related to semaphores or kthreads
@@ -155,7 +155,7 @@ static void reset_tchain_times(struct timer_chain *tchain)
        }
 }
 
-static void init_alarm_service(void)
+static void __attribute__((constructor)) init_alarm_service(void)
 {
        int ctlfd, timerfd, alarmid;
        struct event_queue *ev_q;
@@ -201,7 +201,6 @@ static void init_alarm_service(void)
 void init_awaiter(struct alarm_waiter *waiter,
                   void (*func) (struct alarm_waiter *awaiter))
 {
-       run_once_racy(init_alarm_service());
        waiter->wake_up_time = ALARM_POISON_TIME;
        assert(func);
        waiter->func = func;