diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-06-18 03:07:12 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2000-06-18 03:07:12 +0000 |
commit | f40b1844bbc82657058d3d74837d7e4adbcbfaaa (patch) | |
tree | 279ad134bb13f9a7d1a5aa7e646ca1adc83bd145 /sys/crypto/crypto.c | |
parent | 1d583a1122bd1eb2b9b0237d368b7010e1cbaf3b (diff) |
Crypto kernel thread interface; requests are enqueued and processed by
a kernel thread. This allows a much cleaner interface with respect to
spl levels.
Diffstat (limited to 'sys/crypto/crypto.c')
-rw-r--r-- | sys/crypto/crypto.c | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/sys/crypto/crypto.c b/sys/crypto/crypto.c index a88d56b300f..d9fb8d7f5cb 100644 --- a/sys/crypto/crypto.c +++ b/sys/crypto/crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto.c,v 1.7 2000/06/06 06:49:47 deraadt Exp $ */ +/* $OpenBSD: crypto.c,v 1.8 2000/06/18 03:07:11 angelos Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) @@ -42,9 +42,15 @@ int crypto_drivers_num = 0; struct cryptop *cryptop_queue = NULL; struct cryptodesc *cryptodesc_queue = NULL; + int crypto_queue_num = 0; int crypto_queue_max = CRYPTO_MAX_CACHED; +struct cryptop *crp_req_queue = NULL; +struct cryptop **crp_req_queue_tail = NULL; + +int crypto_invoke(struct cryptop *); + /* * Create a new session. */ @@ -158,7 +164,7 @@ crypto_get_driverid(void) if (crypto_drivers_num == 0) { - crypto_drivers_num = CRYPTO_DRIVERS_INITIAL; + crypto_drivers_num = CRYPTO_DRIVERS_INITIAL; MALLOC(crypto_drivers, struct cryptocap *, crypto_drivers_num * sizeof(struct cryptocap), M_XDATA, M_DONTWAIT); @@ -275,11 +281,31 @@ crypto_unregister(u_int32_t driverid, int alg) } /* - * Dispatch a crypto request to the appropriate crypto devices. + * Add crypto request to a queue, to be processed by a kernel thread. */ int crypto_dispatch(struct cryptop *crp) { + int s = splhigh(); + + if (crp_req_queue == NULL) + crp_req_queue = crp; + else + crp->crp_next = NULL; + + crp_req_queue_tail = &(crp->crp_next); + wakeup((caddr_t) &crp_req_queue); + splx(s); + + return 0; +} + +/* + * Dispatch a crypto request to the appropriate crypto devices. + */ +int +crypto_invoke(struct cryptop *crp) +{ struct cryptodesc *crd; u_int64_t nid; u_int32_t hid; @@ -339,10 +365,13 @@ void crypto_freereq(struct cryptop *crp) { struct cryptodesc *crd; + int s; if (crp == NULL) return; + s = splhigh(); + while ((crd = crp->crp_desc) != NULL) { crp->crp_desc = crd->crd_next; @@ -365,6 +394,8 @@ crypto_freereq(struct cryptop *crp) cryptop_queue = crp; crypto_queue_num++; } + + splx(s); } /* @@ -375,13 +406,17 @@ crypto_getreq(int num) { struct cryptodesc *crd; struct cryptop *crp; + int s = splhigh(); if (cryptop_queue == NULL) { MALLOC(crp, struct cryptop *, sizeof(struct cryptop), M_XDATA, M_DONTWAIT); if (crp == NULL) - return NULL; + { + splx(s); + return NULL; + } } else { @@ -400,6 +435,7 @@ crypto_getreq(int num) M_XDATA, M_DONTWAIT); if (crd == NULL) { + splx(s); crypto_freereq(crp); return NULL; } @@ -416,5 +452,41 @@ crypto_getreq(int num) crp->crp_desc = crd; } + splx(s); return crp; } + +/* + * Crypto thread, runs as a kernel thread to process crypto requests. + */ +void +crypto_thread(void) +{ + struct cryptop *crp; + int s; + + s = splhigh(); + + for (;;) + { + crp = crp_req_queue; + if (crp == NULL) /* No work to do */ + { + (void) tsleep(&crp_req_queue, PLOCK, "crypto_wait", 0); + continue; + } + + /* Remove from the queue */ + crp_req_queue = crp->crp_next; + if (crp_req_queue) + crp_req_queue_tail = &crp_req_queue->crp_next; + else + crp_req_queue_tail = NULL; + + splx(s); + + crypto_invoke(crp); + + s = splhigh(); + } +} |