/* * Find the resolution of the high-resolution clock by sampling successive * values until a tick boundary, at which point the delta is entered into * a table. An average near the median of the table is taken and returned * as the system tick size to eliminate outliers due to descheduling (high) * or tv0 not being the "zero" time in a given tick (low). * * Some trickery is needed to defeat the habit systems have of always * incrementing the microseconds field from gettimeofday() results so that * no two calls return the same value. Thus, a "tick boundary" is assumed * when successive calls return a difference of more than MINTICK ticks. * (For gettimeofday(), this is set to 2 us.) This catches cases where at * most one other task reads the clock between successive reads by this task. * More tasks in between are rare enough that they'll get cut off by the * median filter. * * When a tick boundary is found, the *first* time read during the previous * tick (tv0) is subtracted from the new time to get microseconds per tick. * * Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but * there is ~50 us of system-call overhead to get it, so this overestimates * the tick size considerably. On SunOS 5.x/Solaris, the overhead has been * cut to about 2.5 us, so the measured time alternates between 2 and 3 us. * Some better algorithms will be required for future machines that really * do achieve 1 us granularity. * * Current best idea: discard all this hair and use Ueli Maurer's entropy * estimation scheme. Assign each input event (delta) a sequence number. * 16 bits should be more than adequate. Make a table of the last time * (by sequence number) each possibe input event occurred. For practical * implementation, hash the event to a fixed-size code and consider two * events identical if they have the same hash code. This will only ever * underestimate entropy. Then use the number of bits in the difference * between the current sequence number and the previous one as the entropy * estimate. * * If it's desirable to use longer contexts, Maurer's original technique * just groups events into non-overlapping pairs and uses the technique on * the pairs. If you want to increment the entropy numbers on each keystroke * for user-interface niceness, you can do the operation each time, but you * have to halve the sequence number difference before starting, and then you * have to halve the number of bits of entropy computed because you're adding * them twice. * * You can put the even and odd events into separate tables to close Maurer's * model exactly, or you can just dump them into the same table, which will * be more conservative. */ static PGPUInt32 ranTickSize(void) { int i = 0, j = 0; PGPUInt32 diff, d[kNumDeltas]; timetype tv0, tv1, tv2; /* * TODO Get some per-run data to seed the RNG with. * pid, ppid, etc. */ GetClock(&tv0); tv1 = tv0; do { GetClock(&tv2); diff = tickdiff(tv2, tv1); if (diff > MINTICK) { d[i++] = diff; tv0 = tv2; j = 0; } else if (++j >= 4096) /* Always getting <= MINTICK units */ return MINTICK + !MINTICK; tv1 = tv2; } while (i < kNumDeltas); /* Return average of middle 5 values (rounding up) */ qsort(d, kNumDeltas, sizeof(d[0]), ranCompare); diff = (d[kNumDeltas / 2 - 2] + d[kNumDeltas / 2 - 1] + d[kNumDeltas / 2] + d[kNumDeltas / 2 + 1] + d[kNumDeltas/2 + 2] + 4) / 5; #if NOISEDEBUG fprintf(stderr, "Tick size is %u\n", diff); #endif return diff; }
/* * Find the resolution of the high-resolution clock by sampling successive * values until a tick boundary, at which point the delta is entered into * a table. An average near the median of the table is taken and returned * as the system tick size to eliminate outliers due to descheduling (high) * or tv0 not being the "zero" time in a given tick (low). * * Some trickery is needed to defeat the habit systems have of always * incrementing the microseconds field from gettimeofday() results so that * no two calls return the same value. Thus, a "tick boundary" is assumed * when successive calls return a difference of more than MINTICK ticks. * (For gettimeofday(), this is set to 2 us.) This catches cases where at * most one other task reads the clock between successive reads by this task. * More tasks in between are rare enough that they'll get cut off by the * median filter. * * When a tick boundary is found, the *first* time read during the previous * tick (tv0) is subtracted from the new time to get microseconds per tick. * * Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but * there is ~50 us of system-call overhead to get it, so this overestimates * the tick size considerably. On SunOS 5.x/Solaris, the overhead has been * cut to about 2.5 us, so the measured time alternates between 2 and 3 us. * Some better algorithms will be required for future machines that really * do achieve 1 us granularity. * * Current best idea: discard all this hair and use Ueli Maurer's entropy * estimation scheme. Assign each input event (delta) a sequence number. * 16 bits should be more than adequate. Make a table of the last time * (by sequence number) each possibe input event occurred. For practical * implementation, hash the event to a fixed-size code and consider two * events identical if they have the same hash code. This will only ever * underestimate entropy. Then use the number of bits in the difference * between the current sequence number and the previous one as the entropy * estimate. * * If it's desirable to use longer contexts, Maurer's original technique * just groups events into non-overlapping pairs and uses the technique on * the pairs. If you want to increment the entropy numbers on each keystroke * for user-interface niceness, you can do the operation each time, but you * have to halve the sequence number difference before starting, and then you * have to halve the number of bits of entropy computed because you're adding * them twice. * * You can put the even and odd events into separate tables to close Maurer's * model exactly, or you can just dump them into the same table, which will * be more conservative. */ static unsigned noiseTickSize(void) { unsigned i = 0, j = 0, diff, d[N]; timetype tv0, tv1, tv2; gettime(&tv0); tv1 = tv0; do { gettime(&tv2); diff = (unsigned)tickdiff(tv2, tv1); if (diff > MINTICK) { d[i++] = diff; tv0 = tv2; j = 0; } else if (++j >= 4096) /* Always getting <= MINTICK units */ return MINTICK + !MINTICK; tv1 = tv2; } while (i < N); /* Return average of middle 5 values (rounding up) */ qsort(d, N, sizeof(d[0]), noiseCompare); diff = (d[N/2-2]+d[N/2-1]+d[N/2]+d[N/2+1]+d[N/2+2]+4)/5; #if NOISEDEBUG fprintf(stderr, "Tick size is %u\n", diff); #endif return diff; }
/* * Add as much timing-dependent random noise as possible * to the randPool. Typically, this involves reading the most * accurate system clocks available. * * Returns the number of ticks that have passed since the last call, * for entropy estimation purposes. */ PGPUInt32 pgpRandomCollectEntropy(PGPRandomContext const *rc) { PGPUInt32 delta; timetype t; static PGPUInt32 ticksize = 0; static timetype prevt; GetClock(&t); pgpRandomAddBytes(rc, (PGPByte const *)&t, sizeof(t)); if (!ticksize) { ticksize = ranTickSize(); prevt = t; } delta = (PGPUInt32)(tickdiff(t, prevt) / ticksize); prevt = t; return delta; }
StackTrace::~StackTrace() { m_iStackNum--; strcpy(m_szCurrent, m_pNodes[m_iStackNum].m_szFunction); if(m_pNodes[m_iStackNum].m_bLogging == true) { debug("%-*s%s exit (mem: %ld bytes, %ld ms)\n", m_iStackNum, "", m_pNodes[m_iStackNum].m_szFunction, memusage(), tickdiff(m_pNodes[m_iStackNum].m_dTick)); } }
int main(int argc, char **argv) { int iDebugLevel = 0, iNumMsgs = 0; long lMessageID = -1, lParentID = -1, lFolderID = -1, lDate = 0, lFromID = -1, lToID = -1; char *szSQL = NULL; bytes *pText = NULL, *pSubject = NULL, *pEDF = NULL; EDF *pSearch = NULL; DBTable *pTable = NULL; double dTick = 0; if(argc != 3 || !(strcmp(argv[1], "-edf") == 0 || strcmp(argv[1], "-query") == 0)) { printf("Usage: Searching -edf <file>\n"); printf("Usage: Searching -query <string>\n"); return 1; } if(strcmp(argv[1], "-edf") == 0) { pSearch = EDFParser::FromFile(argv[2]); if(pSearch == NULL) { printf("Could not parse %s, %s\n", argv[2], strerror(errno)); return 1; } EDFParser::Print("Search", pSearch); } else { pSearch = QueryToEDF(argv[2]); printf("Query %s\n", argv[2]); EDFParser::Print("Search", pSearch); // return 0; } printf("\n"); dTick = gettick(); szSQL = MessageSQL(pSearch); printf("SQL(%ld ms): %s\n", tickdiff(dTick), szSQL); if(szSQL == NULL) { printf("Nothing to search for\n"); return 1; } if(DBTable::Connect("ua27") == false) { printf("Cannot connect to database, %s\n", strerror(errno)); delete pSearch; return 1; } pTable = new DBTable(); printf("Binding columns\n"); // messageid pTable->BindColumnInt(); // parentid pTable->BindColumnInt(); // treeid, date, fromid, toid, text pTable->BindColumnInt(); pTable->BindColumnInt(); pTable->BindColumnInt(); pTable->BindColumnInt(); pTable->BindColumnBytes(); // subject pTable->BindColumnBytes(); // edf pTable->BindColumnBytes(); dTick = gettick(); printf("Running query\n"); if(pTable->Execute(szSQL) == true) { printf("Execute(%ld ms)\n", tickdiff(dTick)); // iDebugLevel = debuglevel(DEBUGLEVEL_DEBUG); dTick = gettick(); while(pTable->NextRow() == true) { iNumMsgs++; lMessageID = -1; lParentID = -1; lFolderID = -1; lDate = 0; lFromID = -1; lToID = -1; pText = NULL; pSubject = NULL; pEDF = NULL; // messageid pTable->GetField(0, &lMessageID); // parentid pTable->GetField(1, &lParentID); // treeid, date, fromid, toid, text pTable->GetField(2, &lFolderID); pTable->GetField(3, &lDate); pTable->GetField(4, &lFromID); pTable->GetField(5, &lToID); pTable->GetField(6, &pText); // subject pTable->GetField(7, &pSubject); // edf pTable->GetField(7, &pEDF); printf("m=%ld p=%ld f=%ld d=%ld %ld %ld", lMessageID, lParentID, lFolderID, lDate, lFromID, lToID); if(pSubject != NULL) { printf(", %s", (char *)pSubject->Data(false)); } if(pText != NULL) { printf(":\n%s", (char *)pText->Data(false)); } printf("\n"); // delete pEDF; // delete pSubject; // delete pText; } // debuglevel(iDebugLevel); printf("Found %d messages(%ld ms)\n", iNumMsgs, tickdiff(dTick)); } else { printf("Query failed, %s\n", strerror(errno)); } delete pTable; DBTable::Disconnect(); delete[] szSQL; delete pSearch; return 0; }
/* * Add as much environmentally-derived random noise as possible * to the randPool. Typically, this involves reading the most * accurate system clocks available. * * Returns the number of ticks that have passed since the last call, * for entropy estimation purposes. */ word32 noise(void) { word32 delta; #if defined(MSDOS) static unsigned deltamask = 0; static unsigned prevt; unsigned t; time_t tnow; clock_t cnow; if (deltamask == 0) deltamask = has8254() ? 0xffff : 0x7fff; t = (deltamask & 0x8000) ? read8254() : read8253(); randPoolAddBytes((byte const *)&t, sizeof(t)); delta = deltamask & (t - prevt); prevt = t; /* Add more-significant time components. */ cnow = clock(); randPoolAddBytes((byte *)&cnow, sizeof(cnow)); tnow = time((time_t *)0); randPoolAddBytes((byte *)&tnow, sizeof(tnow)); /* END OF DOS */ #elif defined(VMS) word32 t[2]; /* little-endian 64-bit timer */ word32 d1; /* MSW of difference */ static word32 prevt[2]; SYS$GETTIM(t); /* VMS hardware clock increments by 100000 per tick */ randPoolAddBytes((byte const *)t, sizeof(t)); /* Get difference in d1 and delta, and old time in prevt */ d1 = t[1] - prevt[1] + (t[0] < prevt[0]); prevt[1] = t[1]; delta = t[0] - prevt[0]; prevt[0] = t[0]; /* Now, divide the 64-bit value by 100000 = 2^5 * 5^5 = 32 * 3125 */ /* Divide value, MSW in d1 and LSW in delta, by 32 */ delta >>= 5; delta |= d1 << (32-5); d1 >>= 5; /* * Divide by 3125. This fits into 16 bits, so the following * code is possible. 2^32 = 3125 * 1374389 + 1671. * * This code has confused people reading it, so here's a detailed * explanation. First, since we only want a 32-bit result, * reduce the input mod 3125 * 2^32 before starting. This * amounts to reducing the most significant word mod 3125 and * leaving the least-significant word alone. * * Then, using / for mathematical (real, not integer) division, we * want to compute floor(d1 * 2^32 + d0) / 3125), which I'll denote * using the old [ ] syntax for floor, so it's * [ (d1 * 2^32 + d0) / 3125 ] * = [ (d1 * (3125 * 1374389 + 1671) + d0) / 3125 ] * = [ d1 * 1374389 + (d1 * 1671 + d0) / 3125 ] * = d1 * 137438 + [ (d1 * 1671 + d0) / 3125 ] * = d1 * 137438 + [ d0 / 3125 ] + [ (d1 * 1671 + d0 % 3125) / 3125 ] * * The C / operator, applied to integers, performs [ a / b ], so * this can be implemented in C, and since d1 < 3125 (by the first * modulo operation), d1 * 1671 + d0 % 3125 < 3125 * 1672, which * is 5225000, less than 2^32, so it all fits into 32 bits. */ d1 %= 3125; /* Ignore overflow past 32 bits */ delta = delta/3125 + d1*1374389 + (delta%3125 + d1*1671) / 3125; /* END OF VMS */ #elif defined(UNIX) timetype t; static unsigned ticksize = 0; static timetype prevt; gettime(&t); #if CHOICE_GETITIMER /* If itimer isn't started, start it */ if (t.it_value.tv_sec == 0 && t.it_value.tv_usec == 0) { /* * start the timer - assume that PGP won't be running for * more than 11 days, 13 hours, 46 minutes and 40 seconds. */ t.it_value.tv_sec = 1000000; t.it_interval.tv_sec = 1000000; t.it_interval.tv_usec = 0; signal(SIGALRM, SIG_IGN); /* just in case.. */ setitimer(ITIMER_REAL, &t, NULL); t.it_value.tv_sec = 0; } randPoolAddBytes((byte const *)&t.it_value, sizeof(t.it_value)); #else randPoolAddBytes((byte const *)&t, sizeof(t)); #endif if (!ticksize) ticksize = noiseTickSize(); delta = (word32)(tickdiff(t, prevt) / ticksize); prevt = t; /* END OF UNIX */ #else #error Unknown OS - define UNIX or MSDOS or add code for high-resolution timers #endif return delta; }