#include "resource.h" #include /** * Internal structure for building a priority queue * of processes waiting for the resource to become free. */ typedef struct ResourceWaiter { PriNode link; struct Observer *owner; } ResourceWaiter; bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest) { bool success = false; ASSERT(releaseRequest); sem_obtain(&res->lock); if (res->owner == releaseRequest) { // Already ours res->pri = pri; success = true; } else if (!res->owner) { // Trivial acquire: nobody was owning the resource res->pri = pri; res->owner = releaseRequest; success = true; } else { ResourceWaiter waiter; // Setup waiter structure and enqueue it to resource waiter.owner = releaseRequest; waiter.link.pri = pri; LIST_ENQUEUE(&res->queue, &waiter.link); // Resource busy: are we eligible for preemption? if ((res->pri < pri) && res->owner->event) res->owner->event(EVENT_RELEASE, res); // Wait in the queue until the timeout occurs. do { sem_release(&res->lock); // TODO: use a semaphore here instead ResMan_sleep(); sem_obtain(&res->lock); // Check for ownership if (res->owner == releaseRequest) { success = true; break; } } while (timeout--); // Remove pending waiter if (!success) REMOVE(&waiter.link.link); } sem_release(&res->lock); return success; } void ResMan_Free(Resource *res) { ResourceWaiter *waiter; sem_obtain(&res->lock); ASSERT(res->owner); //TODO: check for real owner calling free // Check for new owner candidates. if ((waiter = (ResourceWaiter *)list_remHead(&res->queue))) { // Transfer ownership of the resource res->owner = waiter->owner; res->pri = waiter->link.pri; //ResMan_wakeup(waiter); } else { // Nobody waiting, free the resource res->owner = NULL; res->pri = -1; } sem_release(&res->lock); } void ResMan_Init(Resource *res) { res->owner = NULL; res->pri = -1; sem_init(&res->lock); LIST_INIT(&res->queue); }