mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
poll: use spinlocks rather than mutexes for use in higher IPLs
This commit is contained in:
@@ -3,21 +3,20 @@
|
|||||||
|
|
||||||
#include <kernel/scheduler.h>
|
#include <kernel/scheduler.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <mutex.h>
|
|
||||||
|
|
||||||
struct polldata;
|
struct polldata;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
thread_t *thread;
|
thread_t *thread;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
mutex_t eventlock;
|
spinlock_t eventlock;
|
||||||
struct polldata *data;
|
struct polldata *data;
|
||||||
struct polldata *event;
|
struct polldata *event;
|
||||||
size_t size;
|
size_t size;
|
||||||
} polldesc_t;
|
} polldesc_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mutex_t lock;
|
spinlock_t lock;
|
||||||
struct polldata *data;
|
struct polldata *data;
|
||||||
} pollheader_t;
|
} pollheader_t;
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ typedef struct polldata {
|
|||||||
} polldata_t;
|
} polldata_t;
|
||||||
|
|
||||||
#define POLL_INITHEADER(x) \
|
#define POLL_INITHEADER(x) \
|
||||||
MUTEX_INIT(&(x)->lock);
|
SPINLOCK_INIT((x)->lock);
|
||||||
|
|
||||||
int poll_initdesc(polldesc_t *, size_t size);
|
int poll_initdesc(polldesc_t *, size_t size);
|
||||||
void poll_add(pollheader_t *, polldata_t *, int events);
|
void poll_add(pollheader_t *, polldata_t *, int events);
|
||||||
|
|||||||
+26
-17
@@ -39,7 +39,7 @@ int poll_initdesc(polldesc_t *desc, size_t size) {
|
|||||||
desc->thread = _cpu()->thread;
|
desc->thread = _cpu()->thread;
|
||||||
desc->size = size;
|
desc->size = size;
|
||||||
SPINLOCK_INIT(desc->lock);
|
SPINLOCK_INIT(desc->lock);
|
||||||
MUTEX_INIT(&desc->eventlock);
|
SPINLOCK_INIT(desc->eventlock);
|
||||||
for (uintmax_t i = 0; i < size; ++i)
|
for (uintmax_t i = 0; i < size; ++i)
|
||||||
desc->data[i].desc = desc;
|
desc->data[i].desc = desc;
|
||||||
__assert(spinlock_try(&desc->lock));
|
__assert(spinlock_try(&desc->lock));
|
||||||
@@ -48,11 +48,13 @@ int poll_initdesc(polldesc_t *desc, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void poll_add(pollheader_t *header, polldata_t *data, int events) {
|
void poll_add(pollheader_t *header, polldata_t *data, int events) {
|
||||||
MUTEX_ACQUIRE(&header->lock, false);
|
bool intstate = interrupt_set(false);
|
||||||
|
spinlock_acquire(&header->lock);
|
||||||
data->events = events;
|
data->events = events;
|
||||||
data->header = header;
|
data->header = header;
|
||||||
insertinheader(header, data);
|
insertinheader(header, data);
|
||||||
MUTEX_RELEASE(&header->lock);
|
spinlock_release(&header->lock);
|
||||||
|
interrupt_set(intstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_leave(polldesc_t *desc) {
|
void poll_leave(polldesc_t *desc) {
|
||||||
@@ -61,29 +63,35 @@ void poll_leave(polldesc_t *desc) {
|
|||||||
if (header == NULL)
|
if (header == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MUTEX_ACQUIRE(&header->lock, false);
|
bool intstate = interrupt_set(false);
|
||||||
|
spinlock_acquire(&header->lock);
|
||||||
removefromlist(&header->data, &desc->data[i]);
|
removefromlist(&header->data, &desc->data[i]);
|
||||||
MUTEX_RELEASE(&header->lock);
|
spinlock_release(&header->lock);
|
||||||
|
interrupt_set(intstate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timeout(context_t *, dpcarg_t arg) {
|
static void timeout(context_t *, dpcarg_t arg) {
|
||||||
polldesc_t *desc = arg;
|
polldesc_t *desc = arg;
|
||||||
|
|
||||||
MUTEX_TRY(&desc->eventlock);
|
bool intstate = interrupt_set(false);
|
||||||
|
spinlock_acquire(&desc->eventlock);
|
||||||
|
|
||||||
if (spinlock_try(&desc->lock))
|
if (spinlock_try(&desc->lock))
|
||||||
sched_wakeup(desc->thread, 1);
|
sched_wakeup(desc->thread, 1);
|
||||||
|
|
||||||
MUTEX_RELEASE(&desc->eventlock);
|
spinlock_release(&desc->eventlock);
|
||||||
|
interrupt_set(intstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
int poll_dowait(polldesc_t *desc, size_t ustimeout) {
|
int poll_dowait(polldesc_t *desc, size_t ustimeout) {
|
||||||
timerentry_t sleepentry = {0};
|
timerentry_t sleepentry = {0};
|
||||||
|
|
||||||
MUTEX_ACQUIRE(&desc->eventlock, false);
|
bool intstate = interrupt_set(false);
|
||||||
|
spinlock_acquire(&desc->eventlock);
|
||||||
if (desc->event) {
|
if (desc->event) {
|
||||||
MUTEX_RELEASE(&desc->eventlock);
|
spinlock_release(&desc->eventlock);
|
||||||
|
interrupt_set(intstate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +103,7 @@ int poll_dowait(polldesc_t *desc, size_t ustimeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&desc->lock);
|
spinlock_release(&desc->lock);
|
||||||
MUTEX_RELEASE(&desc->eventlock);
|
spinlock_release(&desc->eventlock);
|
||||||
int ret = sched_yield();
|
int ret = sched_yield();
|
||||||
// on return, the desc lock is REQUIRED to be left locked by the poll_event function.
|
// on return, the desc lock is REQUIRED to be left locked by the poll_event function.
|
||||||
// XXX interruptible wait breaks this
|
// XXX interruptible wait breaks this
|
||||||
@@ -106,13 +114,16 @@ int poll_dowait(polldesc_t *desc, size_t ustimeout) {
|
|||||||
sched_targetcpu(NULL);
|
sched_targetcpu(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interrupt_set(intstate);
|
||||||
|
|
||||||
ret = ret == 1 ? 0 : ret;
|
ret = ret == 1 ? 0 : ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_event(pollheader_t *header, int events) {
|
void poll_event(pollheader_t *header, int events) {
|
||||||
MUTEX_ACQUIRE(&header->lock, false);
|
bool intstate = interrupt_set(false);
|
||||||
|
spinlock_acquire(&header->lock);
|
||||||
polldata_t *pending = header->data;
|
polldata_t *pending = header->data;
|
||||||
header->data = NULL;
|
header->data = NULL;
|
||||||
polldata_t *iterator = pending;
|
polldata_t *iterator = pending;
|
||||||
@@ -120,7 +131,7 @@ void poll_event(pollheader_t *header, int events) {
|
|||||||
while (iterator) {
|
while (iterator) {
|
||||||
polldesc_t *desc = iterator->desc;
|
polldesc_t *desc = iterator->desc;
|
||||||
polldata_t *next = iterator->next;
|
polldata_t *next = iterator->next;
|
||||||
MUTEX_ACQUIRE(&desc->eventlock, false);
|
spinlock_acquire(&desc->eventlock);
|
||||||
int revents = iterator->events & events;
|
int revents = iterator->events & events;
|
||||||
|
|
||||||
if (spinlock_try(&desc->lock) == false) {
|
if (spinlock_try(&desc->lock) == false) {
|
||||||
@@ -133,13 +144,11 @@ void poll_event(pollheader_t *header, int events) {
|
|||||||
desc->event = iterator;
|
desc->event = iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_RELEASE(&desc->eventlock);
|
spinlock_release(&desc->eventlock);
|
||||||
|
|
||||||
iterator = next;
|
iterator = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipl = interrupt_raiseipl(IPL_DPC);
|
|
||||||
|
|
||||||
iterator = pending;
|
iterator = pending;
|
||||||
while (iterator) {
|
while (iterator) {
|
||||||
polldata_t *next = iterator->next;
|
polldata_t *next = iterator->next;
|
||||||
@@ -148,8 +157,8 @@ void poll_event(pollheader_t *header, int events) {
|
|||||||
iterator = next;
|
iterator = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_RELEASE(&header->lock);
|
spinlock_release(&header->lock);
|
||||||
interrupt_loweripl(ipl);
|
interrupt_set(intstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_destroydesc(polldesc_t *desc) {
|
void poll_destroydesc(polldesc_t *desc) {
|
||||||
|
|||||||
Reference in New Issue
Block a user