Medições negativas do ciclo de clock com rdtsc back-to-back?

Eu estou escrevendo um código C para medir o número de ciclos de clock necessários para adquirir um semáforo. Estou usando o rdtsc e, antes de fazer a medição no semáforo, chamo o rdtsc duas vezes consecutivas para medir a sobrecarga. Eu repito isso muitas vezes, em um loop for, e então eu uso o valor médio como sobrecarga de rdtsc.

Isso está correto, para usar o valor médio, em primeiro lugar?

No entanto, o grande problema aqui é que às vezes recebo valores negativos para a sobrecarga (não necessariamente a média, mas pelo menos os parciais dentro do loop for).

Isso também afeta o cálculo consecutivo do número de ciclos de cpu necessários para osem_wait() operação, que às vezes também se revela negativa. Se o que eu escrevi não está claro, aqui está uma parte do código em que estou trabalhando.

Por que estou recebendo valores tão negativos?

(nota do editor: verObter contagem de ciclos da CPU? para obter uma maneira correta e portátil de obter o registro de data e hora completo de 64 bits. A"=A" A restrição ASM só irá obter os 32 bits baixos ou altos quando compilados para x86-64, dependendo se a alocação de registradores acontece para escolher RAX ou RDX para ouint64_t saída. Não vai pegaredx:eax.)

(segunda nota do editor: oops, essa é a resposta para porque estamos obtendo resultados negativos. Ainda vale a pena deixar uma nota aqui como um aviso para não copiarrdtsc implementação.)

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

static inline uint64_t get_cycles()
{
  uint64_t t;
           // editor's note: "=A" is unsafe for this in x86-64
  __asm volatile ("rdtsc" : "=A"(t));
  return t;
}

int num_measures = 10;

int main ()
{
   int i, value, res1, res2;
   uint64_t c1, c2;
   int tsccost, tot, a;

   tot=0;    

   for(i=0; i<num_measures; i++)
   {    
      c1 = get_cycles();
      c2 = get_cycles();

      tsccost=(int)(c2-c1);


      if(tsccost<0)
      {
         printf("####  ERROR!!!   ");
         printf("rdtsc took %d clock cycles\n", tsccost);
         return 1;
      }   
      tot = tot+tsccost;
   }

   tsccost=tot/num_measures;
   printf("rdtsc takes on average: %d clock cycles\n", tsccost);      

   return EXIT_SUCCESS;
}

questionAnswers(9)

yourAnswerToTheQuestion