[mercury-users] Native garbage collector for Mercury

Thomas Charles CONWAY conway at cs.mu.OZ.AU
Mon Sep 14 09:56:30 AEST 1998


Ralph Becket, you write:
> Yes; still, I'd be uncomfortable if I had to write a device driver in
> Mercury - mind you, it's just the sort of experiment that tends to
> produce interesting results...  One of these days...

There has been some interesting work done in this area at Kent - using
a modified gofer on a small 68k system - I don't have the names/URLs handy.

Assuming that we neaten up some of the signed/unsigned and word length
issues (which are not issues for most code, of course), modelling memory
mapped I/O is fairly easy at the "bare metal" level:

:- module low_level_io.

:- interface.

:- import_module io.

:- type	io_port.

:- pred register_io_port(word, io_port, io__state, io__state).
:- mode register_io_port(in, out, di, uo) is det.

:- pred read_from_io_port(io_port, byte, io__state, io__state).
:- mode read_from_io_port(in, out, di, uo) is det.

:- pred write_to_io_port(io_port, byte, io__state, io__state).
:- mode write_to_io_port(in, in, di, uo) is det.

:- implementation.

:- import_module spinlocks.

:- type io_port
	--->	port(
			word,	% address
			lock
		).

register_io_port(Addr, port(Addr, Lock)) -->
	init_lock(Lock).

read_from_io_port(port(Addr, Lock), Byte) -->
	lock(Lock),
	read_from_io_port0(Addr, Byte),
	unlock(Lock).

:- pred read_from_io_port0(word, byte, io__state, io__state).
:- mode read_from_io_port0(in, out, di, uo) is det.

:- pragma c_code(read_from_io_port0(Addr::in, Byte::out, IO0::di, IO::uo),
		[will_not_call_mercury, thread_safe], "
	Byte = *Addr;
	IO = IO0;
").

write_to_io_port(port(Addr, Lock), Byte) -->
	lock(Lock),
	write_to_io_port0(Addr, Byte),
	unlock(Lock).

:- pred write_to_io_port0(word, byte, io__state, io__state).
:- mode write_to_io_port0(in, out, di, uo) is det.

:- pragma c_code(write_to_io_port0(Addr::in, Byte::in, IO0::di, IO::uo),
		[will_not_call_mercury, thread_safe], "
	*Addr = Byte;
	IO = IO0;
").


Then on top of this, you could implement the appropriate device protocols.
Of course, this approach on its own requires polling, rather than supporting
interrupt driven io (which is of course how you really want to do io).

One easy way of dealing with interrupts is to provide a way of arranging
for a closure to be evaluated on a given interrupt:

:- type signal	== word.

:- pred handler(signal, pred(io__state, io__state), io__state, io__state).
:- mode handler(in, pred(di, uo) is det, di, uo) is det.

Now, of course, for some kinds of signal, we need to be sure that
certain things wan't happen (eg We might need to forbid the handler
from allocating memory). Typeclasses might be a mechanism we can use
to address this sort of problem, or we might need pragmas or something.

All in all, I think the most difficult problem in writing an OS in Mercury
will be finding the labour - I think we have (most of) the wherewithall
to do the job.

Thomas
-- 
Thomas Conway <conway at cs.mu.oz.au>
Nail here [] for new monitor.  )O+



More information about the users mailing list