#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h> // For sysconf

// 随机数更新函数 (与原版相同)
void GenerateRandomNumber(unsigned int *rand1_h, unsigned int *rand1_l) {
    unsigned long long x = (unsigned long long)*rand1_h;
    x *= 0x6AC690C5;
    x += *rand1_l;
    *rand1_h = (unsigned int)x;
    *rand1_l = (unsigned int)(x >> 32);
}

// 定义传递给线程的参数结构体
typedef struct {
    unsigned int start;
    unsigned int end;
    unsigned int search_val;
} ThreadArgs;

// 全局互斥锁，只用于保护printf函数，防止输出混乱
pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;

// 线程执行的函数
void* search_worker(void* args) {
    ThreadArgs* t_args = (ThreadArgs*)args;
    unsigned int begin_h = t_args->end;
    unsigned int begin_l = t_args->start;
    unsigned int search_val = t_args->search_val;

    // *** 核心改动：不再提前退出，每个线程必须完成自己的任务 ***
    for (unsigned int i = begin_l; i < begin_h; ++i) {
        unsigned int h = i;
        unsigned int l = 0x29A;
        GenerateRandomNumber(&h, &l);
        GenerateRandomNumber(&h, &l);

        if (l == search_val) {
            // 找到结果，锁住互斥锁以安全地打印
            pthread_mutex_lock(&printf_mutex);
            printf("找到啦~! 密码是 %08X (由线程 %lu 找到)\n", i, pthread_self());
            pthread_mutex_unlock(&printf_mutex);
            // *** 核心改动：不再退出，继续搜索本线程范围内的其他可能解 ***
        }
    }
    pthread_exit(NULL);
}

int main() {
    time_t begin_time, end_time;
    const unsigned int search_val = 0x39A6FFBB;
    
    // 注意：原程序的循环条件是 i < 0xFFFFFFFF，所以它本身不会测试 0xFFFFFFFF
    // 为了保持行为一致，我们将总范围设为 0xFFFFFFFF
    const unsigned long long total_range_end = 0xFFFFFFFF;

    long num_threads = sysconf(_SC_NPROCESSORS_ONLN);
    if (num_threads <= 0) {
        num_threads = 4; // 默认值
    }
    printf("这是一个修正后的Pthreads并行搜索程序，将使用 %ld 个线程。\n", num_threads);

    begin_time = time(NULL);

    pthread_t threads[num_threads];
    ThreadArgs thread_args[num_threads];
    
    // 注意数据类型，防止溢出
    unsigned long long chunk_size = total_range_end / num_threads;

    for (long i = 0; i < num_threads; ++i) {
        thread_args[i].start = i * chunk_size;
        // 最后一个线程负责处理余下的所有范围
        thread_args[i].end = (i == num_threads - 1) ? total_range_end : (i + 1) * chunk_size;
        thread_args[i].search_val = search_val;

        if (pthread_create(&threads[i], NULL, search_worker, &thread_args[i]) != 0) {
            perror("Failed to create thread");
            return 1;
        }
    }

    // 等待所有线程完成
    for (long i = 0; i < num_threads; ++i) {
        if (pthread_join(threads[i], NULL) != 0) {
            perror("Failed to join thread");
            return 2;
        }
    }

    end_time = time(NULL);
    printf("耗时 %ld 秒~~\n", end_time - begin_time);

    return 0;
}

