libmcl-sys 0.1.2-rc3

This system crate provides Rust language bindings to the Minos Compute Library (MCL)
Documentation
#include <pthread.h>
#include <uthash.h>

#include <atomics.h>
#include <minos.h>
#include <minos_internal.h>
#include <minos_sched_internal.h>

pthread_rwlock_t rdata_lock;
sched_rdata *rdata_hash;

#ifdef _DEBUG
static inline int rdata_print(void) {
    sched_rdata *s;

    for (s = rdata_hash; s != NULL; s = (sched_rdata *)(s->hh.next))
        Dprintf("\t\t Entry <%" PRIu64 ",%" PRIu64 ">", s->key[0], s->key[1]);
    return 0;
}
#else
#define rdata_print()
#endif

int process_cmp(process_t *p1, process_t *p2) {
    return p1->pid - p2->pid;
}

int sched_rdata_init(void) {
    Dprintf("Initializing resident data hash table...");
    pthread_rwlock_init(&rdata_lock, NULL);
    rdata_hash = NULL;
    return 0;
}

static inline sched_rdata *rdata_get_internal(sched_rdata *el) {
    sched_rdata *r = NULL;
    HASH_FIND(hh, rdata_hash, &(el->key), 2 * sizeof(uint64_t), r);
    return r;
}

int sched_rdata_add(sched_rdata *el) {
    sched_rdata *r = NULL;
    pthread_rwlock_wrlock(&rdata_lock);
    HASH_FIND(hh, rdata_hash, &(el->key), 2 * sizeof(uint64_t), r);
    if (r) {
        pthread_rwlock_unlock(&rdata_lock);
        return 1;
    }
    HASH_ADD(hh, rdata_hash, key, 2 * sizeof(uint64_t), el);
    pthread_rwlock_unlock(&rdata_lock);

    Dprintf("\t\t Added <%d,%" PRIu64 "> to rdata hash table",
            el->pid, el->mem_id);
    return 0;
}

sched_rdata *sched_rdata_get(uint64_t mem_id, pid_t pid) {
    sched_rdata *ret = NULL;
    sched_rdata el;

    memset(&el, 0, sizeof(sched_rdata));
    el.pid = pid;
    el.mem_id = mem_id;

    Dprintf("\t Searching for <%d,%" PRIu64 "> in resident data hash table...",
            el.pid, el.mem_id);

    pthread_rwlock_rdlock(&rdata_lock);
    ret = rdata_get_internal(&el);
    pthread_rwlock_unlock(&rdata_lock);

    return ret;
}

sched_rdata *sched_rdata_rm(uint64_t mem_id, pid_t pid) {
    Dprintf("\t Removing Entry <%d,%" PRIu64 ">",
            pid, mem_id);

    sched_rdata *ret = NULL;
    sched_rdata el;
    memset(&el, 0, sizeof(sched_rdata));
    el.key[0] = 0;
    el.key[1] = 0;
    el.pid = pid;
    el.mem_id = mem_id;

    pthread_rwlock_wrlock(&rdata_lock);

    ret = rdata_get_internal(&el);
    if (ret) {
        HASH_DEL(rdata_hash, ret);
    }

    pthread_rwlock_unlock(&rdata_lock);

    return ret;
}

int sched_rdata_rm_pid(pid_t pid, uint64_t *mem_freed, uint64_t ndevs) {
    sched_rdata *s;
    sched_rdata *tmp;
    memset(mem_freed, 0, ndevs * sizeof(uint64_t));

    Dprintf("Removing PID from hash table: %d", pid);
    pthread_rwlock_wrlock(&rdata_lock);
    HASH_ITER(hh, rdata_hash, s, tmp) {
        if (s->pid == pid) {
            Dprintf("\t Removing Entry <%d,%" PRIu64 ">", s->pid, s->mem_id);
            HASH_DEL(rdata_hash, s);
            for (int i = 0; i < ndevs; i++) {
                if (((s->devs >> i) & 0x01)) {
                    VDprintf("\t\t Memory to free on device %d: %" PRIu64 "", i, s->size);
                    mem_freed[i] += s->size;
                }
            }
            free(s);
        }
    }
    pthread_rwlock_unlock(&rdata_lock);

    return 0;
}

int sched_rdata_free(void) {
    sched_rdata *s;
    sched_rdata *tmp;

    Dprintf("Cleaning up resident data hash table...");
    pthread_rwlock_wrlock(&rdata_lock);
    HASH_ITER(hh, rdata_hash, s, tmp) {
        Dprintf("\t Removing Entry <%" PRIu64 ",%" PRIu64 ">", s->key[0], s->key[1]);

        HASH_DEL(rdata_hash, s);
        free(s);
    }

    pthread_rwlock_unlock(&rdata_lock);

    return 0;
}

int sched_rdata_add_device(sched_rdata *el, int dev) {
    Dprintf("\t Adding device %d for <%d,%" PRIu64 "> in hash table...",
            dev, el->pid, el->mem_id);

    int cur_devs = el->devs;
    el->devs |= (0x01 << dev);
    if ((cur_devs >> dev) & 0x01) {
        return 1;
    }
    el->ndevs += 1;
    return 0;
}

int sched_rdata_rm_device(sched_rdata *el, int dev) {
    int cur_devs = el->devs;
    el->devs &= ~(0x01 << dev);
    if (((cur_devs >> dev) & 0x01)) {
        el->ndevs -= 1;
        int64_t cur_idx = el->subbuffers.head;
        mcl_partition_t *cur;
        while (cur_idx >= 0) {
            cur = list_get(&el->subbuffers, cur_idx);
            cur_idx = cur->next;
            if (cur->dev == dev) {
                list_delete(&el->subbuffers, cur);
            }
        }
    }

    return ((cur_devs >> dev) & 0x01);
}

int sched_rdata_on_device(sched_rdata *el, int dev) {
    return ((el->devs >> dev) & 0x01);
}