--- /dev/null
+
+#include "resource.h"
+#include <mware/observer.h>
+
+/**
+ * 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);
+}
+
--- /dev/null
+#ifndef MWARE_RESOURCE_H
+#define MWARE_RESOURCE_H
+
+#include <drv/timer.h> // time_t
+#include <kern/sem.h>
+
+/*
+ * Abstract locking primitives used by host OS.
+ */
+#if CONFIG_KERNEL
+
+ typedef Semaphore ResourceLock;
+ #define ResMan_sleep() timer_delay(1)
+ #define ResMan_time_t mtime_t
+
+#else /* FreeRTOS */
+
+ #include <freertos.h>
+ #include <semphr.h>
+ #include <task.h> // vTaskDelay()
+
+ #define ResMan_sleep() vTaskDelay((portTickType)1 * portTICK_RATE_MS)
+ #define ResMan_time_t portTickType
+#endif
+
+
+// Forward decl
+struct Observer;
+
+/**
+ * Hold context information for a resource such as an audio channel.
+ *
+ * Each driver registers one or more Resource instances with the
+ * ResMan using ResMan_Register().
+ *
+ * Clients can then allocate the resource through ResMan_Alloc()
+ * providing a desired priority and an Observer for asynchronous
+ * notification.
+ *
+ * Allocated resources can be stolen by other clients asking for a
+ * higher priority. ResMan notifies a preemption request by invoking
+ * the Observer of the current owner.
+ *
+ * The Observer callback must take whatever action is needed to
+ * release the resource as soon as possible to avoid blocking the
+ * new owner.
+ */
+typedef struct Resource
+{
+//Private
+ /// Control access to fields below.
+ Semaphore lock;
+
+ /// Pointer to current owner's observer. NULL if resource is free.
+ struct Observer *owner;
+
+ /// Priority of current owner (higher values mean higher priority).
+ int pri;
+
+ /// Queue of processes waiting to obtain the resource.
+ List queue;
+} Resource;
+
+/// Event sent by ResMan to owners when to request resource release.
+enum { EVENT_RELEASE = 1 };
+
+/// Try to allocate a resource \a res with priority \a pri for at most \a timeout ticks.
+bool ResMan_Alloc(Resource *res, int pri, ResMan_time_t timeout, struct Observer *releaseRequest);
+
+/// Free resource \a res. Will eventually wake-up other queued owners.
+void ResMan_Free(Resource *res);
+
+void ResMan_Init(Resource *res);
+
+#endif /* MWARE_RESOURCE_H */