summaryrefslogtreecommitdiffstats
path: root/src/mpq.h
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 08:38:50 +0200
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 08:38:50 +0200
commitf43505b4059220f294a4676308d6d82aa3876018 (patch)
treea816b8f38cb12d67cb6763819baea46f0b37cd3b /src/mpq.h
parentRefactor {send,recv}_transport to return status (diff)
downloadwireguard-openbsd-f43505b4059220f294a4676308d6d82aa3876018.tar.xz
wireguard-openbsd-f43505b4059220f294a4676308d6d82aa3876018.zip
Changing mpq.h again
Diffstat (limited to 'src/mpq.h')
-rw-r--r--src/mpq.h210
1 files changed, 92 insertions, 118 deletions
diff --git a/src/mpq.h b/src/mpq.h
index 9af2ca8e086..ee1aabce470 100644
--- a/src/mpq.h
+++ b/src/mpq.h
@@ -17,161 +17,135 @@
#ifndef _MPQ_H_
#define _MPQ_H_
-#include <sys/types.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
#include <sys/systm.h>
struct mpq {
- struct mutex mpq_mtx;
- size_t mpq_len, mpq_maxlen, mpq_phead, mpq_shead, mpq_tail;
- void **mpq_items;
+ struct mutex mpq_mtx;
+ struct mbuf_list mpq_list;
+ struct mbuf *mpq_cursor;
+ void *mpq_serializer;
};
-struct mpq_commit {
- void **itemp;
-};
-
-void mpq_init(struct mpq *, int, size_t);
-void mpq_destroy(struct mpq *);
-int mpq_enqueue(struct mpq *, void *);
-void *mpq_parallel(struct mpq *, struct mpq_commit *);
-void mpq_parallel_commit(struct mpq *, struct mpq_commit *, void *);
-void *mpq_serial(struct mpq *);
-
-#define MPQ_ITEM(mpq, item) ((mpq)->mpq_items[(mpq)->item])
-#define MPQ_INC(mpq, item) ((mpq)->item = ((mpq)->item + 1) % (mpq)->mpq_maxlen)
-#define MPQ_LOAD(mpq, item) ((mpq)->item <= (mpq)->mpq_tail ? \
- (mpq)->mpq_tail - (mpq)->item : (mpq)->mpq_maxlen - (mpq)->item + (mpq)->mpq_tail)
+void mpq_init(struct mpq *, int);
+int mpq_serialize_try_enter(struct mpq *);
+void mpq_serialize_leave(struct mpq *);
+void mpq_enqueue(struct mpq *, struct mbuf *);
+void mpq_enlist(struct mpq *, struct mbuf_list *);
+struct mbuf *mpq_dethread(struct mpq *);
+struct mbuf *mpq_dequeue(struct mpq *);
+void mpq_done(struct mbuf *m);
+void mpq_dead(struct mbuf *m);
+
+#define MPQ_WORKER(fn_name, parallel_fn, serial_fn) \
+void fn_name(struct mpq *mpq) { \
+ struct mbuf *m; \
+ while ((m = mpq_dethread(mpq)) != NULL) { \
+ if (parallel_fn(m) == 0) \
+ mpq_done(m); \
+ else \
+ mpq_dead(m); \
+ \
+ if (mpq_serialize_try_enter(mpq) == 0) { \
+ while((m = mpq_dequeue(mpq)) != NULL) { \
+ serial_fn(m); \
+ } \
+ mpq_serialize_leave(mpq); \
+ } \
+ } \
+} \
void
-mpq_init(struct mpq *mpq, int ipl, size_t len)
+mpq_init(struct mpq *mpq, int ipl)
{
- bzero(mpq, sizeof(*mpq));
+ mpq->mpq_cursor = NULL;
+ mpq->mpq_serializer = NULL;
mtx_init(&mpq->mpq_mtx, ipl);
- mpq->mpq_items = mallocarray(len, sizeof(void *), M_DEVBUF, M_WAITOK);
- mpq->mpq_maxlen = len;
+ ml_init(&mpq->mpq_list);
}
-void *
-mpq_parallel(struct mpq *mpq, struct mpq_commit *commit)
+int
+mpq_serialize_try_enter(struct mpq *mpq)
{
- void *item = NULL;
+ int error = 1;
mtx_enter(&mpq->mpq_mtx);
- item = MPQ_ITEM(mpq, mpq_phead);
- if (item != NULL) {
- commit->itemp = &MPQ_ITEM(mpq, mpq_phead);
- MPQ_ITEM(mpq, mpq_phead) = NULL;
- MPQ_INC(mpq, mpq_phead);
- } else {
- commit->itemp = NULL;
+ if (mpq->mpq_serializer == NULL) {
+ mpq->mpq_serializer = curcpu();
+ error = 0;
}
mtx_leave(&mpq->mpq_mtx);
- return item;
+ return error;
}
void
-mpq_parallel_commit(struct mpq *mpq, struct mpq_commit *commit, void *item)
+mpq_serialize_leave(struct mpq *mpq)
{
mtx_enter(&mpq->mpq_mtx);
- *commit->itemp = item;
+ mpq->mpq_serializer = NULL;
mtx_leave(&mpq->mpq_mtx);
}
-void *
-mpq_serial(struct mpq *mpq)
+void
+mpq_enqueue(struct mpq *mpq, struct mbuf *m)
{
- void *item = NULL;
+ CLR(m->m_flags, M_PROTO1);
+ CLR(m->m_flags, M_LINK0);
mtx_enter(&mpq->mpq_mtx);
- item = MPQ_ITEM(mpq, mpq_shead);
- if (item != NULL && mpq->mpq_phead != mpq->mpq_shead) {
- MPQ_ITEM(mpq, mpq_shead) = NULL;
- MPQ_INC(mpq, mpq_shead);
- }
+ ml_enqueue(&mpq->mpq_list, m);
mtx_leave(&mpq->mpq_mtx);
- return item;
}
-int
-mpq_enqueue(struct mpq *mpq, void *item)
+void
+mpq_enlist(struct mpq *mpq, struct mbuf_list *list)
{
- int dropped = 0;
- assert(item != NULL);
mtx_enter(&mpq->mpq_mtx);
- if (MPQ_LOAD(mpq, mpq_shead) < mpq->mpq_maxlen - 1) {
- MPQ_ITEM(mpq, mpq_tail) = item;
- MPQ_INC(mpq, mpq_tail);
- } else {
- dropped = 1;
- }
+ ml_enlist(&mpq->mpq_list, list);
mtx_leave(&mpq->mpq_mtx);
-
- return dropped;
}
-/* TESTS (need to comment out sys/systm.h in mpq.h includes)
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#define mallocarray(a, b, _x, _y) malloc((a) * (b))
-#define bzero(a, b) memset(a, 0, b);
-#include "mpq.h"
-
-void __mtx_init(struct mutex *a, int b) {}
-void mtx_enter(struct mutex *a) {}
-void mtx_leave(struct mutex *a) {}
-
-int
-main(int argc, char *argv[])
+struct mbuf
+*mpq_dethread(struct mpq *mpq)
{
- int ret;
- size_t i;
- struct mpq_commit commit, falsecommit;
- struct mpq test_mpq;
- mpq_init(&test_mpq, 0, 4);
-
- // basic test
- assert(mpq_parallel(&test_mpq, &commit) == NULL);
- assert(commit.itemp == NULL);
- assert(mpq_serial(&test_mpq) == NULL);
+ struct mbuf *m;
+ mtx_enter(&mpq->mpq_mtx);
+ if (mpq->mpq_cursor == NULL)
+ mpq->mpq_cursor = MBUF_LIST_FIRST(&mpq->mpq_list);
+ else
+ mpq->mpq_cursor = MBUF_LIST_NEXT(mpq->mpq_cursor);
+ m = mpq->mpq_cursor;
+ mtx_leave(&mpq->mpq_mtx);
+ return m;
+}
- for (i = 1; i < 8; i++) {
- ret = mpq_enqueue(&test_mpq, (void *)i);
- assert(ret == (i < 4 ? 0 : 1));
+struct mbuf
+*mpq_dequeue(struct mpq *mpq)
+{
+ struct mbuf *m = NULL;
+ struct mbuf_list freeq = MBUF_LIST_INITIALIZER();
+ mtx_enter(&mpq->mpq_mtx);
+ while (ISSET(MBUF_LIST_FIRST(&mpq->mpq_list)->m_flags, M_LINK0)) {
+ m = ml_dequeue(&mpq->mpq_list);
+ if (ISSET(m->m_flags, M_PROTO1))
+ break;
+ ml_enqueue(&freeq, m);
+ m = NULL;
}
-
- assert(mpq_parallel(&test_mpq, &commit) == (void *)1);
- assert(mpq_serial(&test_mpq) == NULL);
- mpq_parallel_commit(&test_mpq, &commit, (void *) 1);
- assert(mpq_serial(&test_mpq) == (void *)1);
-
- assert(mpq_parallel(&test_mpq, &commit) == (void *)2);
- mpq_parallel_commit(&test_mpq, &commit, (void *) 2);
- assert(mpq_parallel(&test_mpq, &commit) == (void *)3);
- mpq_parallel_commit(&test_mpq, &commit, (void *) 3);
-
- assert(mpq_parallel(&test_mpq, &commit) == NULL);
-
- assert(mpq_serial(&test_mpq) == (void *)2);
- assert(mpq_serial(&test_mpq) == (void *)3);
- assert(mpq_serial(&test_mpq) == NULL);
-
- // test replacement
-
- mpq_enqueue(&test_mpq, (void *)1);
-
- assert(mpq_parallel(&test_mpq, &commit) == (void *)1);
- assert(mpq_parallel(&test_mpq, &falsecommit) == NULL);
- mpq_parallel_commit(&test_mpq, &commit, (void *) 2);
- assert(mpq_parallel(&test_mpq, &commit) == NULL);
- assert(mpq_serial(&test_mpq) == (void *)2);
- assert(mpq_serial(&test_mpq) == NULL);
-
- printf("Passed!!\n");
+ mtx_leave(&mpq->mpq_mtx);
+ ml_purge(&freeq);
+ return m;
}
-*/
+void
+mpq_done(struct mbuf *m)
+{
+ SET(m->m_flags, M_PROTO1);
+ SET(m->m_flags, M_LINK0);
+}
+void
+mpq_dead(struct mbuf *m)
+{
+ SET(m->m_flags, M_LINK0);
+}
#endif /* _MPQ_H_ */