Exemplo n.º 1
0
// Convert the statistics into ML data.  This is further unpicked within ML.
static Handle unpackStats(TaskData *taskData, const polystatistics *stats)
{
    // Vector for the counts.  Initially created as mutable then locked.
    Handle counts = alloc_and_save(taskData, N_PS_COUNTERS, F_MUTABLE_BIT);
    for (unsigned i = 0; i < N_PS_COUNTERS; i++)
    {
        Handle mark = taskData->saveVec.mark();
        Handle counterValue = Make_arbitrary_precision(taskData, stats->psCounters[i]);
        counts->WordP()->Set(i, counterValue->Word());
        taskData->saveVec.reset(mark);
    }
    // Can now lock the count vector by removing the mutable flag.
    counts->WordP()->SetLengthWord(N_PS_COUNTERS);

    // Vector for the sizes.
    Handle sizes = alloc_and_save(taskData, N_PS_SIZES, F_MUTABLE_BIT);
    for (unsigned j = 0; j < N_PS_SIZES; j++)
    {
        Handle mark = taskData->saveVec.mark();
        Handle sizeValue = Make_arbitrary_precision(taskData, stats->psSizes[j]);
        sizes->WordP()->Set(j, sizeValue->Word());
        taskData->saveVec.reset(mark);
    }
    sizes->WordP()->SetLengthWord(N_PS_SIZES);

    // Vector for the times.
    Handle times = alloc_and_save(taskData, N_PS_TIMES, F_MUTABLE_BIT);
    for (unsigned k = 0; k < N_PS_TIMES; k++)
    {
        Handle mark = taskData->saveVec.mark();
#ifdef HAVE_WINDOWS_H
        Handle sizeValue = Make_arb_from_Filetime(taskData, stats->psTimers[k]);
#else
        Handle sizeValue =
            Make_arb_from_pair_scaled(taskData, stats->psTimers[k].tv_sec, stats->psTimers[k].tv_usec, 1000000);
#endif
        times->WordP()->Set(k, sizeValue->Word());
        taskData->saveVec.reset(mark);
    }
    times->WordP()->SetLengthWord(N_PS_TIMES);

    // Vector for the user stats
    Handle users = alloc_and_save(taskData, N_PS_USER, F_MUTABLE_BIT);
    for (unsigned l = 0; l < N_PS_USER; l++)
    {
        Handle mark = taskData->saveVec.mark();
        Handle userValue = Make_arbitrary_precision(taskData, stats->psUser[l]);
        users->WordP()->Set(l, userValue->Word());
        taskData->saveVec.reset(mark);
    }
    users->WordP()->SetLengthWord(N_PS_USER);

    // Result vector
    Handle resultVec = alloc_and_save(taskData, 4);
    resultVec->WordP()->Set(0, counts->Word());
    resultVec->WordP()->Set(1, sizes->Word());
    resultVec->WordP()->Set(2, times->Word());
    resultVec->WordP()->Set(3, users->Word());
    return resultVec;
}
Exemplo n.º 2
0
Handle HeapSizeParameters::getGCStime(TaskData *taskData) const
{
#if (defined(_WIN32) && ! defined(__CYGWIN__))
    return Make_arb_from_pair(taskData, ((FILETIME)totalGCSystemCPU).dwHighDateTime, ((FILETIME)totalGCSystemCPU).dwLowDateTime);
#else
    return Make_arb_from_pair_scaled(taskData, ((struct timeval)totalGCSystemCPU).tv_sec, ((struct timeval)totalGCSystemCPU).tv_usec, 1000000);
#endif
}
Exemplo n.º 3
0
Handle HeapSizeParameters::getGCUtime(TaskData *taskData) const
{
#if (defined(_WIN32) && ! defined(__CYGWIN__))
    return Make_arb_from_Filetime(taskData, totalGCUserCPU);
#else
    return Make_arb_from_pair_scaled(taskData, ((struct timeval)totalGCUserCPU).tv_sec, ((struct timeval)totalGCUserCPU).tv_usec, 1000000);
#endif
}
Exemplo n.º 4
0
Handle timing_dispatch_c(TaskData *taskData, Handle args, Handle code)
{
    unsigned c = get_C_unsigned(taskData, DEREFWORDHANDLE(code));
    switch (c)
    {
    case 0: /* Get ticks per microsecond. */
        return Make_arbitrary_precision(taskData, TICKS_PER_MICROSECOND);
    case 1: /* Return time since the time base. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            FILETIME ft;
            GetSystemTimeAsFileTime(&ft);
            return Make_arb_from_Filetime(taskData, ft);
#else
            struct timeval tv;
            if (gettimeofday(&tv, NULL) != 0)
                raise_syscall(taskData, "gettimeofday failed", errno);
            return Make_arb_from_pair_scaled(taskData, tv.tv_sec, tv.tv_usec, 1000000);
#endif
        }
    case 2: /* Return the base year.  This is the year which corresponds to
               zero in the timing sequence. */
#if (defined(_WIN32) && ! defined(__CYGWIN__))
        return Make_arbitrary_precision(taskData, 1601);
#else
        return Make_arbitrary_precision(taskData, 1970);
#endif

    case 3: /* In both Windows and Unix the time base is 1st of January
               in the base year.  This function is provided just in case
               we are running on a system with a different base.  It
               returns the number of seconds after 1st January of the
               base year that corresponds to zero of the time base. */
        return Make_arbitrary_precision(taskData, 0);

    case 4: /* Return the time offset which applied/will apply at the
               specified time (in seconds). */
        {
            int localoff = 0;
            time_t theTime;
            int day = 0;
#if (defined(HAVE_GMTIME_R) || defined(HAVE_LOCALTIME_R))
            struct tm result;
#endif
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            /* Although the offset is in seconds it is since 1601. */
            FILETIME ftSeconds; // Not really a file-time because it's a number of seconds.
            getFileTimeFromArb(taskData, args, &ftSeconds); /* May raise exception. */
            ULARGE_INTEGER   liTime;
            liTime.HighPart = ftSeconds.dwHighDateTime;
            liTime.LowPart = ftSeconds.dwLowDateTime;
            theTime = (long)(liTime.QuadPart - SECSSINCE1601);
#else
            theTime = get_C_long(taskData, DEREFWORDHANDLE(args)); /* May raise exception. */
#endif

            {
#ifdef HAVE_GMTIME_R
                struct tm *loctime = gmtime_r(&theTime, &result);
#else
                PLocker lock(&timeLock);
                struct tm *loctime = gmtime(&theTime);
#endif
                if (loctime == NULL) raise_exception0(taskData, EXC_size);
                localoff = (loctime->tm_hour*60 + loctime->tm_min)*60 + loctime->tm_sec;
                day = loctime->tm_yday;
            }

            {

#ifdef HAVE_LOCALTIME_R
                struct tm *loctime = localtime_r(&theTime, &result);
#else
                PLocker lock(&timeLock);
                struct tm *loctime = localtime(&theTime);
#endif
                if (loctime == NULL) raise_exception0(taskData, EXC_size);
                localoff -= (loctime->tm_hour*60 + loctime->tm_min)*60 + loctime->tm_sec;
                if (loctime->tm_yday != day)
                {
                    // Different day - have to correct it.  We can assume that there
                    // is at most one day to correct.
                    if (day == loctime->tm_yday+1 || (day == 0 && loctime->tm_yday >= 364))
                        localoff += 24*60*60;
                    else localoff -= 24*60*60;
                }
            }

            return Make_arbitrary_precision(taskData, localoff);
        }

    case 5: /* Find out if Summer Time (daylight saving) was/will be in effect. */
        {
            time_t theTime;
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            FILETIME ftSeconds; // Not really a file-time because it's a number of seconds.
            getFileTimeFromArb(taskData, args, &ftSeconds); /* May raise exception. */
            ULARGE_INTEGER   liTime;
            liTime.HighPart = ftSeconds.dwHighDateTime;
            liTime.LowPart = ftSeconds.dwLowDateTime;
            theTime = (long)(liTime.QuadPart - SECSSINCE1601);
#else
            theTime = get_C_long(taskData, DEREFWORDHANDLE(args)); /* May raise exception. */
#endif
            int isDst = 0;
#ifdef HAVE_LOCALTIME_R
            struct tm result;
            struct tm *loctime = localtime_r(&theTime, &result);
            isDst = loctime->tm_isdst;
#else
            {
                PLocker lock(&timeLock);
                struct tm *loctime = localtime(&theTime);
                if (loctime == NULL) raise_exception0(taskData, EXC_size);
                isDst = loctime->tm_isdst;
            }
#endif
            return Make_arbitrary_precision(taskData, isDst);
        }

    case 6: /* Call strftime.  It would be possible to do much of this in
               ML except that it requires the current locale. */
        {
            struct  tm time;
            char    *format, buff[2048];
            Handle  resString;
            /* Get the format string. */
            format = Poly_string_to_C_alloc(DEREFHANDLE(args)->Get(0));

            /* Copy the time information. */
            time.tm_year = get_C_int(taskData, DEREFHANDLE(args)->Get(1)) - 1900;
            time.tm_mon = get_C_int(taskData, DEREFHANDLE(args)->Get(2));
            time.tm_mday = get_C_int(taskData, DEREFHANDLE(args)->Get(3));
            time.tm_hour = get_C_int(taskData, DEREFHANDLE(args)->Get(4));
            time.tm_min = get_C_int(taskData, DEREFHANDLE(args)->Get(5));
            time.tm_sec = get_C_int(taskData, DEREFHANDLE(args)->Get(6));
            time.tm_wday = get_C_int(taskData, DEREFHANDLE(args)->Get(7));
            time.tm_yday = get_C_int(taskData, DEREFHANDLE(args)->Get(8));
            time.tm_isdst = get_C_int(taskData, DEREFHANDLE(args)->Get(9));
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            _tzset(); /* Make sure we set the current locale. */
#else
            setlocale(LC_TIME, "");
#endif
            /* It would be better to dynamically allocate the string rather
               than use a fixed size but Unix unlike Windows does not distinguish
               between an error in the input and the buffer being too small. */
            if (strftime(buff, sizeof(buff), format, &time) <= 0)
            {
                /* Error */
                free(format);
                raise_exception0(taskData, EXC_size);
            }
            resString = taskData->saveVec.push(C_string_to_Poly(taskData, buff));
            free(format);
            return resString;
        }

    case 7: /* Return User CPU time since the start. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            FILETIME ut, ct, et, kt;
            if (! GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut))
                raise_syscall(taskData, "GetProcessTimes failed", 0-GetLastError());
            return Make_arb_from_Filetime(taskData, ut);
#else
            struct rusage rusage;
            if (getrusage(RUSAGE_SELF, &rusage) != 0)
                raise_syscall(taskData, "getrusage failed", errno);
            return Make_arb_from_pair_scaled(taskData, rusage.ru_utime.tv_sec,
                        rusage.ru_utime.tv_usec, 1000000);
#endif
        }

    case 8: /* Return System CPU time since the start. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            FILETIME ct, et, kt, ut;
            if (! GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut))
                raise_syscall(taskData, "GetProcessTimes failed", 0-GetLastError());
            return Make_arb_from_Filetime(taskData, kt);
#else
            struct rusage rusage;
            if (getrusage(RUSAGE_SELF, &rusage) != 0)
                raise_syscall(taskData, "getrusage failed", errno);
            return Make_arb_from_pair_scaled(taskData, rusage.ru_stime.tv_sec,
                        rusage.ru_stime.tv_usec, 1000000);
#endif
        }

    case 9: /* Return GC time since the start. */
        return gHeapSizeParameters.getGCUtime(taskData);

    case 10: /* Return real time since the start. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            FILETIME ft;
            GetSystemTimeAsFileTime(&ft);
            subFiletimes(&ft, &startTime);
            return Make_arb_from_Filetime(taskData, ft);
#else
            struct timeval tv;
            if (gettimeofday(&tv, NULL) != 0)
                raise_syscall(taskData, "gettimeofday failed", errno);
            subTimevals(&tv, &startTime);
            return Make_arb_from_pair_scaled(taskData, tv.tv_sec, tv.tv_usec, 1000000);
#endif
        }

        /* These next two are used only in the Posix structure. */
    case 11: /* Return User CPU time used by child processes. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            return Make_arbitrary_precision(taskData, 0);
#else
            struct rusage rusage;
            if (getrusage(RUSAGE_CHILDREN, &rusage) != 0)
                raise_syscall(taskData, "getrusage failed", errno);
            return Make_arb_from_pair_scaled(taskData, rusage.ru_utime.tv_sec,
                        rusage.ru_utime.tv_usec, 1000000);
#endif
        }

    case 12: /* Return System CPU time used by child processes. */
        {
#if (defined(_WIN32) && ! defined(__CYGWIN__))
            return Make_arbitrary_precision(taskData, 0);
#else
            struct rusage rusage;
            if (getrusage(RUSAGE_CHILDREN, &rusage) != 0)
                raise_syscall(taskData, "getrusage failed", errno);
            return Make_arb_from_pair_scaled(taskData, rusage.ru_stime.tv_sec,
                        rusage.ru_stime.tv_usec, 1000000);
#endif
        }

    case 13: /* Return GC system time since the start. */
        return gHeapSizeParameters.getGCStime(taskData);

    default:
        {
            char msg[100];
            sprintf(msg, "Unknown timing function: %d", c);
            raise_exception_string(taskData, EXC_Fail, msg);
            return 0;
        }
    }
}