Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <thread.h>
#include "threadimpl.h"

enum
{
        STACK = 8192,
};

void
iointerrupt(Ioproc *io)
{
        if(!io->inuse)
                return;
        threadint(io->tid);
}

static void
xioproc(void *a)
{
        Ioproc *io, *x;
        io = a;
        /*
         * first recvp acquires the ioproc.
         * second tells us that the data is ready.
         */
        for(;;){
                while(recv(io->c, &x) == -1)
                        ;
                if(x == 0)      /* our cue to leave */
                        break;
                assert(x == io);

                /* caller is now committed -- even if interrupted he'll return */
                while(recv(io->creply, &x) == -1)
                        ;
                if(x == 0)      /* caller backed out */
                        continue;
                assert(x == io);

                io->ret = io->op(&io->arg);
                if(io->ret < 0)
                        rerrstr(io->err, sizeof io->err);
                while(send(io->creply, &io) == -1)
                        ;
                while(recv(io->creply, &x) == -1)
                        ;
        }
}

Ioproc*
ioproc(void)
{
        Ioproc *io;

        io = mallocz(sizeof(*io), 1);
        if(io == nil)
                sysfatal("ioproc malloc: %r");
        io->c = chancreate(sizeof(void*), 0);
        io->creply = chancreate(sizeof(void*), 0);
        io->tid = proccreate(xioproc, io, STACK);
        return io;
}

void
closeioproc(Ioproc *io)
{
        if(io == nil)
                return;
        iointerrupt(io);
        while(send(io->c, 0) == -1)
                ;
        chanfree(io->c);
        chanfree(io->creply);
        free(io);
}