
/* cift4-c.c -- CIF test 4, C part */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "cifccsp.h"

void out_string (char *str, Channel *out)
{
	unsigned char *ch = (unsigned char *)str;

	while (*ch != '\0') {
		ChanOutChar (out, *ch);
		ch++;
	}
	return;
}

void proc_p1 (Process *me, Channel *out)
{
	int i;
	Time t;

	for (i=0; i<10; i++) {
		ChanOutInt (out, i);
		ProcTime (&t);
		ProcTimeAfter (ProcTimePlus (t, 500000));
	}
	ChanOutInt (out, -1);
	return;
}

void proc_p2 (Process *me, Channel *in, Channel *key_in, Channel *out)
{
	int v = 0;
	char str[20];

	do {
		int i;
		
		i = ProcAlt (in, key_in, NULL);
		switch (i) {
		case 0:
			ChanInInt (in, &v);
			break;
		case 1:
			v = 0;
			ChanInChar (key_in, (char *)&v);
			break;
		default:
			SetErr ();
			break;
		}
		EXTERNAL_CALLN (sprintf, str, "%d:%d\n", i, v);
		out_string (str, out);
		Reschedule ();
		if ((i == 1) && ((char)v == 'q')) {
			SetErr ();
		} else if ((i == 1) && ((char)v == 'p')) {
			EXTERNAL_CALLN (sprintf, str, "pri=%d\n", GetPri());
			out_string (str, out);
		} else if ((i == 1) && ((char)v == '+')) {
			SetPri (GetPri() - 1);
		} else if ((i == 1) && ((char)v == '-')) {
			SetPri (GetPri() + 1);
		}
	} while (v > -1);
	return;
}

void my_process (Process *me, Channel *kroc_kyb, Channel *kroc_scr)
{
	Process *p1, *p2;
	Channel c;

	ChanInit (&c);
	out_string ("Hello, world! (from C).  Allocating some other processes and going parallel..\n", kroc_scr);
	p1 = ProcAlloc (proc_p1, 4096, 1, &c);
	p2 = ProcAlloc (proc_p2, 4096, 3, &c, kroc_kyb, kroc_scr);

	ProcPar (p1, p2, NULL);

	ProcAllocClean (p1);
	ProcAllocClean (p2);
	return;
}


/* allocates process and returns address to occam world */
void real_cift4_init (int *raddr, Channel *c, Channel *d)
{
	Process *p = ProcAlloc (my_process, 4096, 2, c, d);

	*raddr = (int)p;
	return;
}

/* frees memory used by a process -- lets hope it's finished :) */
void real_cift4_free (int addr)
{
	Process *p = (Process *)addr;

	ProcAllocClean (p);
	return;
}

void _cift4_init (int *ws) { real_cift4_init ((int *)(ws[0]), (Channel *)(ws[1]), (Channel *)(ws[2])); }
void _cift4_free (int *ws) { real_cift4_free ((int)(ws[0])); }

