#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int lock = 0;
int VAR = 0;
int niter = 0;

void increment(int *thread_id)
{
    int tid = *thread_id;
    free(thread_id);

    int step = niter / 4;
    if (step == 0)
        step = 1;

    for (int i = 0; i < niter; i++) {
        futex(&lock, FUTEX_LOCK, 0);

        if (i > 0 && i % step == 0) {
            printf("[T-%d] %d/%d iterations done\n", tid, i, niter);
        }

        int tmp;
        tmp = VAR;
        tmp -= 5;
        VAR = tmp;

        tmp = VAR;
        tmp += 2;
        VAR = tmp;

        tmp = VAR;
        tmp += 4;
        VAR = tmp;

        futex(&lock, FUTEX_UNLOCK, 0);
    }
    futex(&lock, FUTEX_LOCK, 0);
    printf("[T-%d] Finished\n", tid);
    futex(&lock, FUTEX_UNLOCK, 0);

    exit(0);
}

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("Usage: %s <num_threads> <iterations>\n", argv[0]);
        exit(1);
    }
    int nthreads = atoi(argv[1]);
    niter = atoi(argv[2]);

    printf("[main] VAR value: %d, nthreads: %d\n", VAR, nthreads);

    for (int i = 0; i < nthreads; i++) {
        int *thread_id = malloc(sizeof(int));
        *thread_id = i;
        create_thread(increment, thread_id);
    }

    for (int i = 0; i < nthreads; i++) {
        join();
    }

    printf("[main] All threads joined, VAR value: %d, expected: %d\n", VAR, nthreads * niter);
    exit(0);
}
