resource.c
00001
00002 #include "resource.h"
00003 #include <mware/observer.h>
00004
00009 typedef struct ResourceWaiter
00010 {
00011     PriNode link;
00012     struct Observer *owner;
00013
00014 } ResourceWaiter;
00015
00016
00017 bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest)
00018 {
00019     bool success = false;
00020
00021     ASSERT(releaseRequest);
00022
00023     sem_obtain(&res->lock);
00024
00025     if (res->owner == releaseRequest)
00026     {
00027         // Already ours
00028         res->pri = pri;
00029         success = true;
00030     }
00031     else if (!res->owner)
00032     {
00033         // Trivial acquire: nobody was owning the resource
00034         res->pri = pri;
00035         res->owner = releaseRequest;
00036         success = true;
00037     }
00038     else
00039     {
00040         ResourceWaiter waiter;
00041
00042         // Setup waiter structure and enqueue it to resource
00043         waiter.owner = releaseRequest;
00044         waiter.link.pri = pri;
00045         LIST_ENQUEUE(&res->queue, &waiter.link);
00046
00047         // Resource busy: are we eligible for preemption?
00048         if ((res->pri < pri) && res->owner->event)
00049             res->owner->event(EVENT_RELEASE, res);
00050
00051         // Wait in the queue until the timeout occurs.
00052         do
00053         {
00054             sem_release(&res->lock);
00055             // TODO: use a semaphore here instead
00056             ResMan_sleep();
00057             sem_obtain(&res->lock);
00058
00059             // Check for ownership
00060             if (res->owner == releaseRequest)
00061             {
00062                 success = true;
00063                 break;
00064             }
00065         }
00066         while (timeout--);
00067
00068         // Remove pending waiter
00069         if (!success)
00070             REMOVE(&waiter.link.link);
00071     }
00072
00073     sem_release(&res->lock);
00074     return success;
00075 }
00076
00077 void ResMan_Free(Resource *res)
00078 {
00079     ResourceWaiter *waiter;
00080
00081     sem_obtain(&res->lock);
00082
00083
00084     ASSERT(res->owner);
00085     //TODO: check for real owner calling free
00086
00087     // Check for new owner candidates.
00088     if ((waiter = (ResourceWaiter *)list_remHead(&res->queue)))
00089     {
00090         // Transfer ownership of the resource
00091         res->owner = waiter->owner;
00092         res->pri = waiter->link.pri;
00093         //ResMan_wakeup(waiter);
00094     }
00095     else
00096     {
00097         // Nobody waiting, free the resource
00098         res->owner = NULL;
00099         res->pri = -1;
00100     }
00101
00102     sem_release(&res->lock);
00103 }
00104
00105 void ResMan_Init(Resource *res)
00106 {
00107     res->owner = NULL;
00108     res->pri = -1;
00109
00110     sem_init(&res->lock);
00111     LIST_INIT(&res->queue);
00112 }
00113