/* basicdd.c - Basic Device Driver task */

#include <synrtx.h>

#define ACQUIRE    0
#define RELEASE    1
#define EXCEPTION  2 
#define NOBODY     (task_t)0

static task_t owner;

static handler Acquire(msg_t *msg_p) {
    register task_t caller = msg_p->srcTid;
    register task_t self   = msg_p->dstTid;

    owner = caller;

    /* interrupt caller.Grant */
    msg_p->srcTid = self;
    msg_p->dstTid = caller;
    msg_p->dstHid = /* caller's GRANT handler id */
    msg_p->type   = msg_type_SYNC;
    task_interrupt(&msg);
}

static handler Release(msg_t *msg_p) {
    register TID caller = msg_p->srcTid;
    register TID self   = msg_p->dstTid;

    if (owner == caller)
        owner = NOBODY;
    else {
        /* interrupt self.Exception(caller) */
        msg_p->srcTid = msg_p->dstTid = self;
        msg_p->dstHid = EXCEPTION;
        msg_p->type   = msg_type_WORD;
        msg_p->value.w = (word)caller;
        task_interrupt(msg_p);
    }
}

static handler Exception(msg_t *msg_p) {
    io_putf("Illegal Access to Device Driver by Task #%w\n", msg_p->value.w);
}

task BasicDeviceDriver(void) {
    task_setHandler(3, Acquire, Release, Exception);

    owner = NOBODY;
    loop {
        task_enableWait(NO_TIMEOUT, 1, ACQUIRE);
        do  /* The owner can now used the device ...
             * only the client (owner) can release it.
             */
            task_enableWait(NO_TIMEOUT, 2, RELEASE, EXCEPTION);
        while (owner != NOBODY);
        }
    }
}
