summaryrefslogblamecommitdiff
path: root/src/kernel/lib/earray.c
blob: a17e823293922aa2a9e6554ec898e533005354b5 (plain) (tree)



























































































































































                                                                                                    
#include "earray.h"

#include <mem/mem.h>
#include <core/sys.h>

void earray_init(struct earray *array) {
	int i;

	if (array->data != 0) return;

	array->ref_vect_len = array->ref_vect_init_len;
	array->elements = 0;
	array->mutex = MUTEX_UNLOCKED;

	array->data = kmalloc(array->ref_vect_len * sizeof(void***));

	for (i = 0; i < array->ref_vect_len; i++) {
		array->data[i] = 0;
	}
}

void earray_free(struct earray *array) {
	int i;

	mutex_lock(&array->mutex);

	for (i = 0; i < array->ref_vect_len; i++) {
		if (array->data[i] != 0) kfree(array->data[i]);
	}
	kfree(array->data);
	array->data = 0;

	//no need to unlock, the structure is never to be used again
}

int earray_add(struct earray *array, void *ptr) {
	if (ptr == 0) return -1;

	mutex_lock(&array->mutex);

	int i, j;

	for (i = 0; i < array->ref_vect_len; i++) {
		if (array->data[i] == 0) {
			// Allocate here
			array->data[i] = kmalloc(array->vect_len * sizeof(void**));
			array->data[i][0] = ptr;
			for (j = 1; j < array->vect_len; j++) array->data[i][j] = 0;

			j = i * array->vect_len;		//ret val

			if (array->elements <= j) array->elements = j + 1;

			mutex_unlock(&array->mutex);
			return j;
		} else {
			// Look for free space
			for (j = 0; j < array->vect_len; j++) {
				if (array->data[i][j] == 0) {
					array->data[i][j] = ptr;

					j = i * array->vect_len + j;		// ret val
					if (array->elements <= j) array->elements = j + 1;

					mutex_unlock(&array->mutex);
					return j;
				}
			}
		}
	}
	// Nothing was allocated, we need MORE SPACE
	void ***new_data = kmalloc(array->ref_vect_len + array->ref_vect_init_len);
	for (i = 0; i < array->ref_vect_len; i++) {
		new_data[i] = array->data[i];
	}
	new_data[array->ref_vect_len] = kmalloc(array->vect_len * sizeof(void**));
	new_data[array->ref_vect_len][0] = ptr;
	j = array->ref_vect_len * array->vect_len;		// j = return value
	for (i = 1; i < array->vect_len; i++) {
		new_data[array->ref_vect_len][i] = 0;
	}
	for (i = array->ref_vect_len + 1; i < array->ref_vect_len + array->ref_vect_init_len; i++) {
		new_data[i] = 0;
	}
	kfree(array->data);
	array->data = new_data;
	array->ref_vect_len += array->ref_vect_init_len;

	ASSERT(j >= array->elements);
	array->elements = j + 1;

	mutex_unlock(&array->mutex);
	return j;

}

void *earray_at(struct earray *array, int num) {
	mutex_lock(&array->mutex);

	int i = num / array->vect_len, j = num % array->vect_len;
	if (i >= array->ref_vect_len || array->data[i] == 0) return 0;
	void* ret = array->data[i][j];

	mutex_unlock(&array->mutex);
	return ret;
}

void earray_set(struct earray *array, int num, void* ptr) {
	mutex_lock(&array->mutex);

	int a = num / array->vect_len, b = num % array->vect_len, i, j;
	if (a >= array->ref_vect_len) {
		if (ptr == 0) {
			mutex_unlock(&array->mutex);
			return;
		}
		int new_vect_len = array->ref_vect_len;
		while (a >= array->ref_vect_len) new_vect_len += array->ref_vect_init_len;

		void ***new_data = kmalloc(new_vect_len * sizeof(void***));
		for (i = 0; i < array->ref_vect_len; i++) {
			new_data[i] = array->data[i];
		}
		for (i = array->ref_vect_len; i < new_vect_len; i++) {
			new_data[i] = 0;
		}
		kfree(array->data);
		array->data = new_data;
		array->ref_vect_len = new_vect_len;
	}
	if (ptr == 0) {
		if (array->data[a] != 0) {
			if (array->data[a][b] != 0) {
				array->data[a][b] = 0;
				j = 1;
				for (i = 0; i < array->vect_len; i++) {
					if (array->data[a][i] != 0) j = 0;
				}
				if (j == 1) {
					kfree(array->data[a]);
					array->data[a] = 0;
				}
			}
		}
	} else {
		if (array->data[a] = 0) {
			array->data[a] = kmalloc(array->vect_len * sizeof(void**));
			for (i = 0; i < array->vect_len; i++) array->data[a][i] = 0;
		}
		array->data[a][b] = ptr;
		
		if (num >= array->elements) array->elements = num + 1;
	}

	mutex_unlock(&array->mutex);
}