qemu/docs/win32-qemu-event.promela
<<
>>
Prefs
   1/*
   2 * This model describes the implementation of QemuEvent in
   3 * util/qemu-thread-win32.c.
   4 *
   5 * Author: Paolo Bonzini <pbonzini@redhat.com>
   6 *
   7 * This file is in the public domain.  If you really want a license,
   8 * the WTFPL will do.
   9 *
  10 * To verify it:
  11 *     spin -a docs/event.promela
  12 *     gcc -O2 pan.c -DSAFETY
  13 *     ./a.out
  14 */
  15
  16bool event;
  17int value;
  18
  19/* Primitives for a Win32 event */
  20#define RAW_RESET event = false
  21#define RAW_SET   event = true
  22#define RAW_WAIT  do :: event -> break; od
  23
  24#if 0
  25/* Basic sanity checking: test the Win32 event primitives */
  26#define RESET     RAW_RESET
  27#define SET       RAW_SET
  28#define WAIT      RAW_WAIT
  29#else
  30/* Full model: layer a userspace-only fast path on top of the RAW_*
  31 * primitives.  SET/RESET/WAIT have exactly the same semantics as
  32 * RAW_SET/RAW_RESET/RAW_WAIT, but try to avoid invoking them.
  33 */
  34#define EV_SET 0
  35#define EV_FREE 1
  36#define EV_BUSY -1
  37
  38int state = EV_FREE;
  39
  40int xchg_result;
  41#define SET   if :: state != EV_SET ->                                      \
  42                    atomic { /* xchg_result=xchg(state, EV_SET) */          \
  43                        xchg_result = state;                                \
  44                        state = EV_SET;                                     \
  45                    }                                                       \
  46                    if :: xchg_result == EV_BUSY -> RAW_SET;                \
  47                       :: else -> skip;                                     \
  48                    fi;                                                     \
  49                 :: else -> skip;                                           \
  50              fi
  51
  52#define RESET if :: state == EV_SET -> atomic { state = state | EV_FREE; }  \
  53                 :: else            -> skip;                                \
  54              fi
  55
  56int tmp1, tmp2;
  57#define WAIT  tmp1 = state;                                                 \
  58              if :: tmp1 != EV_SET ->                                       \
  59                    if :: tmp1 == EV_FREE ->                                \
  60                          RAW_RESET;                                        \
  61                          atomic { /* tmp2=cas(state, EV_FREE, EV_BUSY) */  \
  62                              tmp2 = state;                                 \
  63                              if :: tmp2 == EV_FREE -> state = EV_BUSY;     \
  64                                 :: else            -> skip;                \
  65                              fi;                                           \
  66                          }                                                 \
  67                          if :: tmp2 == EV_SET -> tmp1 = EV_SET;            \
  68                             :: else           -> tmp1 = EV_BUSY;           \
  69                          fi;                                               \
  70                       :: else -> skip;                                     \
  71                    fi;                                                     \
  72                    assert(tmp1 != EV_FREE);                                \
  73                    if :: tmp1 == EV_BUSY -> RAW_WAIT;                      \
  74                       :: else -> skip;                                     \
  75                    fi;                                                     \
  76                 :: else -> skip;                                           \
  77              fi
  78#endif
  79
  80active proctype waiter()
  81{
  82     if
  83         :: !value ->
  84             RESET;
  85             if
  86                 :: !value -> WAIT;
  87                 :: else   -> skip;
  88             fi;
  89        :: else -> skip;
  90    fi;
  91    assert(value);
  92}
  93
  94active proctype notifier()
  95{
  96    value = true;
  97    SET;
  98}
  99