<commit_before>// Copyright (c) 2010 Baidu, Inc.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Ge,Jun (<EMAIL>)
// Date: Fri Aug 29 15:01:15 CST 2014

#include <unistd.h>                          // close
#include <sys/types.h>                       // open
#include <sys/stat.h>                        // ^
#include <fcntl.h>                           // ^

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <string.h>                          // memmem
#undef _GNU_SOURCE
#include <ctype.h>

#include "butil/time.h"

#if defined(NO_CLOCK_GETTIME_IN_MAC)
#include <mach/clock.h>                      // mach_absolute_time
#include <mach/mach_time.h>                  // mach_timebase_info
#include <pthread.h>                         // pthread_once
#include <stdlib.h>                          // exit

static mach_timebase_info_data_t s_timebase;
static timespec s_init_time;
static uint64_t s_init_ticks;
static pthread_once_t s_init_clock_once = PTHREAD_ONCE_INIT;

static void InitClock() {
    if (mach_timebase_info(&s_timebase) != 0) {
        exit(1);
    }
    timeval now;
    if (gettimeofday(&now, NULL) != 0) {
        exit(1);
    }
    s_init_time.tv_sec = now.tv_sec;
    s_init_time.tv_nsec = now.tv_usec * 1000L;
    s_init_ticks = mach_absolute_time();
}

int clock_gettime(clockid_t id, timespec* time) {
    if (pthread_once(&s_init_clock_once, InitClock) != 0) {
        exit(1);
    }
    uint64_t clock = mach_absolute_time() - s_init_ticks;
    uint64_t elapsed = clock * (uint64_t)s_timebase.numer / (uint64_t)s_timebase.denom;
    *time = s_init_time;
    time->tv_sec += elapsed / 1000000000L;
    time->tv_nsec += elapsed % 1000000000L;
    time->tv_sec += time->tv_nsec / 1000000000L;
    time->tv_nsec = time->tv_nsec % 1000000000L;
    return 0;
}

#endif

namespace butil {

int64_t monotonic_time_ns() {
    // MONOTONIC_RAW is slower than MONOTONIC in linux 2.6.32, trying to
    // use the RAW version does not make sense anymore.
    // NOTE: Not inline to keep ABI-compatible with previous versions.
    timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    return now.tv_sec * 1000000000L + now.tv_nsec;
}

namespace detail {

static int64_t read_cpu_current_frequency(char* buf, ssize_t n) {
    /* We read the information from the /proc filesystem.  It contains at
       least one line like
       cpu MHz         : 497.840237
       or also
       cpu MHz         : 497.841
       We search for this line and convert the number in an integer.  */

    int64_t result = 0;
    char *mhz = static_cast<char*>(memmem(buf, n, "cpu MHz", 7));
    if (mhz != NULL) {
        char *endp = buf + n;
        int seen_decpoint = 0;
        int ndigits = 0;

        /* Search for the beginning of the string.  */
        while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') {
            ++mhz;
        }
        while (mhz < endp && *mhz != '\n') {
            if (*mhz >= '0' && *mhz <= '9') {
                result *= 10;
                result += *mhz - '0';
                if (seen_decpoint)
                    ++ndigits;
            } else if (*mhz == '.') {
                seen_decpoint = 1;
            }
            ++mhz;
        }

        /* Compensate for missing digits at the end.  */
        while (ndigits++ < 6) {
            result *= 10;
        }
    }
    return result;
}

static int64_t read_cpu_frequency_from_brand_string(char* buf, ssize_t n) {
    /* We read the information from the /proc filesystem.  It may contains at
       least one line like
       model name	: Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
       We search for this line and convert the number in an integer.  */

    char* brand = static_cast<char*>(memmem(buf, n, "model name", 10));
    if (brand == NULL) {
        return 0;
    }
    char* end = buf + n;
    char* num_str = brand + 10;
    while (num_str != end && *num_str++ != '@');
    while (num_str != end && !isdigit(*num_str)) {
        num_str++;
    }
    //expect x.xxGhz
    //FSB may be 0.10GHz or 0.133...GHz
    if (end - num_str < 7 || num_str[1] != '.'
        || !isdigit(num_str[2]) || !isdigit(num_str[3]) ||  num_str[4] != 'G') {
        return 0;
    }
    int64_t result = (num_str[0]-'0') * 10 + (num_str[2]-'0');
    int64_t last = num_str[3] - '0';
    if (last == 7) {
        last = 6;
    }
    for (int i = 0; i < 8; i++) {
        result = result * 10 + last;
    }
    return result;
}

#if defined(__x86_64__) || defined(__i386__)
#if defined(__pic__) && defined(__i386__)
static void __cpuid(uint32_t reg[4], uint32_t code) {
    __asm__ volatile (
        "mov %%ebx, %%edi\n"
        "cpuid\n"
        "xchg %%edi, %%ebx\n"
        : "=a"(reg[0]), "=D"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
        : "a"(code)<commit_msg>early fail in cpu brand string analysis<commit_after>// Copyright (c) 2010 Baidu, Inc.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Ge,Jun (<EMAIL>)
// Date: Fri Aug 29 15:01:15 CST 2014

#include <unistd.h>                          // close
#include <sys/types.h>                       // open
#include <sys/stat.h>                        // ^
#include <fcntl.h>                           // ^

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <string.h>                          // memmem
#undef _GNU_SOURCE
#include <ctype.h>

#include "butil/time.h"

#if defined(NO_CLOCK_GETTIME_IN_MAC)
#include <mach/clock.h>                      // mach_absolute_time
#include <mach/mach_time.h>                  // mach_timebase_info
#include <pthread.h>                         // pthread_once
#include <stdlib.h>                          // exit

static mach_timebase_info_data_t s_timebase;
static timespec s_init_time;
static uint64_t s_init_ticks;
static pthread_once_t s_init_clock_once = PTHREAD_ONCE_INIT;

static void InitClock() {
    if (mach_timebase_info(&s_timebase) != 0) {
        exit(1);
    }
    timeval now;
    if (gettimeofday(&now, NULL) != 0) {
        exit(1);
    }
    s_init_time.tv_sec = now.tv_sec;
    s_init_time.tv_nsec = now.tv_usec * 1000L;
    s_init_ticks = mach_absolute_time();
}

int clock_gettime(clockid_t id, timespec* time) {
    if (pthread_once(&s_init_clock_once, InitClock) != 0) {
        exit(1);
    }
    uint64_t clock = mach_absolute_time() - s_init_ticks;
    uint64_t elapsed = clock * (uint64_t)s_timebase.numer / (uint64_t)s_timebase.denom;
    *time = s_init_time;
    time->tv_sec += elapsed / 1000000000L;
    time->tv_nsec += elapsed % 1000000000L;
    time->tv_sec += time->tv_nsec / 1000000000L;
    time->tv_nsec = time->tv_nsec % 1000000000L;
    return 0;
}

#endif

namespace butil {

int64_t monotonic_time_ns() {
    // MONOTONIC_RAW is slower than MONOTONIC in linux 2.6.32, trying to
    // use the RAW version does not make sense anymore.
    // NOTE: Not inline to keep ABI-compatible with previous versions.
    timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    return now.tv_sec * 1000000000L + now.tv_nsec;
}

namespace detail {

static int64_t read_cpu_current_frequency(char* buf, ssize_t n) {
    /* We read the information from the /proc filesystem.  It contains at
       least one line like
       cpu MHz         : 497.840237
       or also
       cpu MHz         : 497.841
       We search for this line and convert the number in an integer.  */

    int64_t result = 0;
    char *mhz = static_cast<char*>(memmem(buf, n, "cpu MHz", 7));
    if (mhz != NULL) {
        char *endp = buf + n;
        int seen_decpoint = 0;
        int ndigits = 0;

        /* Search for the beginning of the string.  */
        while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') {
            ++mhz;
        }
        while (mhz < endp && *mhz != '\n') {
            if (*mhz >= '0' && *mhz <= '9') {
                result *= 10;
                result += *mhz - '0';
                if (seen_decpoint)
                    ++ndigits;
            } else if (*mhz == '.') {
                seen_decpoint = 1;
            }
            ++mhz;
        }

        /* Compensate for missing digits at the end.  */
        while (ndigits++ < 6) {
            result *= 10;
        }
    }
    return result;
}

static int64_t read_cpu_frequency_from_brand_string(char* buf, ssize_t n) {
    /* We read the information from the /proc filesystem.  It may contains at
       least one line like
       model name	: Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz
       We search for this line and convert the number in an integer.  */

    char* brand = static_cast<char*>(memmem(buf, n, "model name", 10));
    if (brand == NULL) {
        return 0;
    }
    char* end = buf + n;
    char* num_str = brand + 10;
    while (num_str != end && *num_str != '@') {
        if (*num_str++ == '\n') {
            return 0;
        }
    }
    while (num_str != end && !isdigit(*num_str)) {
        num_str++;
    }
    //expect x.xxGhz
    //FSB may be 0.10GHz or 0.133...GHz
    if (end - num_str < 7 || num_str[1] != '.'
        || !isdigit(num_str[2]) || !isdigit(num_str[3]) ||  num_str[4] != 'G') {
        return 0;
    }
    int64_t result = (num_str[0]-'0') * 10 + (num_str[2]-'0');
    int64_t last = num_str[3] - '0';
    if (last == 7) {
        last = 6;
    }
    for (int i = 0; i < 8; i++) {
        result = result * 10 + last;
    }
    return result;
}

#if defined(__x86_64__) || defined(__i386__)
#if defined(__pic__) && defined(__i386__)
static void __cpuid(uint32_t reg[4], uint32_t code) {
    __asm__ volatile (
        "mov %%ebx, %%edi\n"
        "cpuid\n"
        "xchg %%edi, %%ebx\n"
        : "=a"(reg[0]), "=D"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
        : "a"(code)
{'fraction_non_alphanumeric': 0.13237356268112555, 'fraction_numerical': 0.03692624100215013, 'mean_word_length': 2.1062717770034842, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 10, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '763976', 'n_tokens_mistral': 4063, 'n_tokens_neox': 3655, 'n_words': 1022}