BeRTOS
|
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