libmcl-sys 0.1.2-rc1

This system crate provides Rust language bindings to the Minos Compute Library (MCL)
Documentation
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

#include <utlist.h>

#include <minos.h>
#include <minos_internal.h>
#include <debug.h>

extern mcl_desc_t mcl_desc;
extern mcl_resource_t* mcl_res;
mcl_kernel* kerMap = NULL;
pthread_rwlock_t kerMap_lock;

static inline int pcmp(mcl_kernel* a, mcl_kernel* b)
{
	return strcmp(a->name, b->name);
}

int kerMap_init(void)
{
	return pthread_rwlock_init(&kerMap_lock, NULL);
}

static inline mcl_kernel* __kerMap_search(char* key)
{
        mcl_kernel* e;

        LL_FOREACH(kerMap,e)
		if(strcmp(e->name, key) == 0)
			return e;

        return NULL;
}

mcl_kernel* kerMap_search(char* key)
{
	mcl_kernel* e;

        Dprintf("\t Looking for kernel %s...", key);
        pthread_rwlock_rdlock(&kerMap_lock);
        e = __kerMap_search(key);
        pthread_rwlock_unlock(&kerMap_lock);
	
	return e;
}

int kerMap_add_prg(mcl_kernel* k, mcl_program* p)
{
        struct kernel_program* kprg;

        kprg = (struct kernel_program*) malloc(sizeof(struct kernel_program));
        if(!kprg){
                eprintf("Error allocating memory for kernel program for kernel %s", k->name);
                return -1;
        }

        pthread_rwlock_wrlock(&(k->lock));
        kprg->p = p;
        LL_APPEND(k->prg, kprg);
        k->targets |= p->targets;
        pthread_rwlock_unlock(&(k->lock));
        Dprintf("\t Added program %s to kernel %s (targets = 0x%lx)", p->key, k->name, k->targets);
        return 0;
}

mcl_program* kerMap_get_prg(mcl_kernel* k, uint64_t device)
{
        mcl_device_t* dev = res_getDev(device);
        struct kernel_program* kprg;
        mcl_program* e = NULL;

        assert(k->targets & dev->type);

        pthread_rwlock_rdlock(&(k->lock));
        LL_FOREACH(k->prg, kprg){
                Dprintf("\t Checking program %s (prg targets 0x%lx, ker targets 0x%lx dev type 0x%lx)",
                kprg->p->key, kprg->p->targets, k->targets, dev->type);
                if(kprg->p->targets & dev->type){
                        e = kprg->p;
                        break;
                }
        }
        pthread_rwlock_unlock(&(k->lock));
        if(e) 
                Dprintf("\t Found program %s", e->key);

        return e;
}

mcl_kernel* kerMap_add(char* name)
{
	mcl_kernel* k   = NULL;
	
	k = kerMap_search(name);
	if(k)
		return k;

	Dprintf("\t Kernel %s not found, adding new one...", name);
	k = (mcl_kernel*) malloc(sizeof(mcl_kernel));
	if(!k){
		eprintf("Error allocating memory for new program (%s)!", name);
		goto err;
	}

	k->name = (char*) malloc(strlen(name) + 1);
        if(k->name == NULL){
                eprintf("Error allocating memory for kernel name (%s)", name);
                goto kernel;
        }
        strcpy(k->name, name);
        k->targets = 0x0;
        k->prg     = NULL;
        pthread_rwlock_init(&(k->lock), NULL);

        pthread_rwlock_wrlock(&kerMap_lock);
	LL_APPEND(kerMap, k);
        pthread_rwlock_unlock(&kerMap_lock);

        Dprintf("\t Kernel %s added (targets = 0x%lx)", k->name, k->targets);
	return k;

kernel:
	free(k);
err:	
	return NULL;
}

static inline void __kerMap_remove(mcl_kernel* k)
{
	Dprintf("Removing kernel %s...", k->name);
	LL_DELETE(kerMap, k);
	free(k->name);
        free(k);
}

int kerMap_remove(mcl_kernel* k)
{
	mcl_kernel* e;

        pthread_rwlock_wrlock(&kerMap_lock);
	LL_SEARCH(kerMap, e, k, pcmp);
	if(e){
		__kerMap_remove(k);
		return 0;
	}
        pthread_rwlock_unlock(&kerMap_lock);
	Dprintf("Kernel %s not found.", k->name);
	
	return 1;
}

void kerMap_finit(void)
{
	mcl_kernel* e;
	mcl_kernel* tmp;
	
	Dprintf("Removing cached programs...");
	LL_FOREACH_SAFE(kerMap, e, tmp){
		__kerMap_remove(e);
		free(e);
	}
}