#include "utils.h"

namespace gpucache {

    __device__ ThreadCtx::ThreadCtx() {
        auto global_thread_id = blockIdx.x * blockDim.x + threadIdx.x;
        global_warp_idx = global_thread_id / warpSize;
        block_warp_idx = threadIdx.x / warpSize;
        lane_id = threadIdx.x % warpSize;
        num_warps = blockDim.x * gridDim.x / warpSize;
    }


    __device__ WarpMutex::WarpMutex() : flag(0) {}

    __device__ void WarpMutex::Lock(ThreadCtx &ctx) {
        if (ctx.lane_id == 0) {
            while (atomicCAS(&flag, 0, 1) != 0) {}
        }
        __threadfence();
        __syncwarp();

    }

    __device__ void WarpMutex::UnLock(ThreadCtx &ctx) {
        __syncwarp();
        __threadfence();
        if (ctx.lane_id == 0) {
            atomicExch(&flag, 0);
        }
    }


    __global__ void initLocks(uint32_t n_bucket, void *bucketMutexes) {
        uint32_t global_thread_idx = blockDim.x * blockIdx.x + threadIdx.x;
        if (global_thread_idx < n_bucket) {
            new(reinterpret_cast<WarpMutex *>(bucketMutexes) + global_thread_idx)
                    WarpMutex();
        }
    }

}


