view runtime/context.c @ 141:f2cb85c53ced

Fix Pause/Resume and rewrite Call Async in Rhope rather than C
author Mike Pavone <pavone@retrodev.com>
date Sat, 20 Nov 2010 17:48:22 -0500
parents c14698c512f1
children 7bbdc034e347
line wrap: on
line source

#include "context.h"
#include "object.h"
#include "thread.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>

context * contextqueue[32];
int32_t cq_readloc=0;
int32_t cq_writeloc=0;
rh_mutex(cq_lock)

void cqueue_init()
{
	rh_mutex_init(cq_lock);
}

context * get_cqueue()
{
	context * ret;
	rh_lock(cq_lock);
		if (cq_readloc == cq_writeloc)
		{
			rh_unlock(cq_lock);
			return NULL;
		}
		ret = contextqueue[cq_readloc++];
		if (cq_readloc == 32)
			cq_readloc = 0;
	rh_unlock(cq_lock);
	return ret;
}

int32_t put_cqueue(context * ct)
{
	rh_lock(cq_lock);
		if ((cq_writeloc+1)&31 == cq_readloc)
		{
			rh_unlock(cq_lock);
			return 0;
		}
		contextqueue[cq_writeloc++] = ct;
	rh_unlock(cq_lock);
	return 1;
}

stackchunk * new_stack()
{
	stackchunk * st = malloc(sizeof(stackchunk));
	st->prev = NULL;
	st->next = NULL;
	st->free_space = st->data;
	return st;
}

context * new_context()
{
	context * c = malloc(sizeof(context));
	c->stack_begin = new_stack();
	c->current_stack = c->stack_begin;
	c->resume_cdata = c->runafter = c->transaction = NULL;	
	c->resumeable = 0;
	return c;
}

void free_context(context * c)
{
	stackchunk *next,*current = c->stack_begin;
	while(current)
	{
		next = current->next;
		free(current);
		current = next;
	}
	free(c);
}

void * alloc_stack(context * ct, uint32_t size)
{
	void * ret;
	stackchunk * current = ct->current_stack;
	char * next_free = current->free_space + size;
	if (next_free <= (current->data + STACK_CHUNK_SIZE))
	{
		ret = current->free_space;
		current->free_space = next_free;
		return ret;
	}
	if (!current->next)
	{
		current->next = new_stack();
		current->next->prev = current;
	}
	current = current->next;
	ct->current_stack = current;
	current->free_space = current->data + size;
	return current->data;
}

calldata * alloc_cdata(context * ct, calldata * lastframe, uint32_t num_params)
{
	//Make sure we have enough space for at least 32 return values
	calldata * retval = alloc_stack(ct, sizeof(calldata)+(31)*sizeof(object *));
	//But only actually reserve space for the number requested
	free_stack(ct, retval->params + num_params);
	retval->lastframe = lastframe;
	retval->callspace = num_params;
	return retval;
}

void free_stack(context * ct, void * data)
{
	char * cdata = data;
	while(cdata < ct->current_stack->data || cdata >= ct->current_stack->free_space)
	{
		if(ct->current_stack == ct->stack_begin)
		{
			fprintf(stderr, "Attempt to free memory at %X using free_stack, but %X doesn't appear to be stack allocated\n", data, data);
			exit(-1);
		}
		ct->current_stack = ct->current_stack->prev;
	}
	ct->current_stack->free_space = data;
	if(ct->current_stack->free_space == ct->current_stack->data && ct->current_stack->prev)
		ct->current_stack = ct->current_stack->prev;
}