BeRTOS
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