summaryrefslogtreecommitdiff
path: root/src/irmd/api_table.c
diff options
context:
space:
mode:
authordimitri staessens <[email protected]>2017-09-30 17:58:18 +0200
committerdimitri staessens <[email protected]>2017-09-30 17:58:18 +0200
commit9405ad97e20686f74c06bcbac9523a8b4f10272e (patch)
treea0489929634ee7588de3ad77a6a1166ce11508e2 /src/irmd/api_table.c
parent5e974395fadc5e1922f200855c14ca0538ba50dc (diff)
downloadouroboros-9405ad97e20686f74c06bcbac9523a8b4f10272e.tar.gz
ouroboros-9405ad97e20686f74c06bcbac9523a8b4f10272e.zip
lib: Cancel tpm threads instead of marking exit
This makes the threadpool use pthread_cancel instead of setting an exit flag that threadpool managed threads check periodically. This drastically reduces CPU consumption in the irmd when running a lot of applications. It requires cancellation handlers in the ipcp and irmd to be implemented to ensure safe cancellation during operation and shutdown.
Diffstat (limited to 'src/irmd/api_table.c')
-rw-r--r--src/irmd/api_table.c91
1 files changed, 50 insertions, 41 deletions
diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c
index df56dd02..a244f3a2 100644
--- a/src/irmd/api_table.c
+++ b/src/irmd/api_table.c
@@ -36,8 +36,6 @@
#include <limits.h>
#include <assert.h>
-#define ENTRY_SLEEP_TIMEOUT 10 /* ms */
-
struct api_entry * api_entry_create(pid_t api,
char * apn)
{
@@ -70,14 +68,14 @@ struct api_entry * api_entry_create(pid_t api,
pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
#endif
- if (pthread_mutex_init(&e->state_lock, NULL)) {
+ if (pthread_mutex_init(&e->lock, NULL)) {
free(e);
return NULL;
}
- if (pthread_cond_init(&e->state_cond, &cattr)) {
- pthread_mutex_destroy(&e->state_lock);
+ if (pthread_cond_init(&e->cond, &cattr)) {
+ pthread_mutex_destroy(&e->lock);
free(e);
return NULL;
}
@@ -85,6 +83,15 @@ struct api_entry * api_entry_create(pid_t api,
return e;
}
+void cancel_api_entry(void * o)
+{
+ struct api_entry * e = (struct api_entry *) o;
+
+ e->state = API_NULL;
+
+ pthread_mutex_unlock(&e->lock);
+}
+
void api_entry_destroy(struct api_entry * e)
{
struct list_head * p;
@@ -92,25 +99,29 @@ void api_entry_destroy(struct api_entry * e)
assert(e);
- pthread_mutex_lock(&e->state_lock);
+ pthread_mutex_lock(&e->lock);
if (e->state == API_DESTROY) {
- pthread_mutex_unlock(&e->state_lock);
+ pthread_mutex_unlock(&e->lock);
return;
}
if (e->state == API_SLEEP)
e->state = API_DESTROY;
- pthread_cond_signal(&e->state_cond);
+ pthread_cond_signal(&e->cond);
+
+ pthread_cleanup_push(cancel_api_entry, e);
while (e->state != API_INIT)
- pthread_cond_wait(&e->state_cond, &e->state_lock);
+ pthread_cond_wait(&e->cond, &e->lock);
+
+ pthread_cleanup_pop(false);
- pthread_mutex_unlock(&e->state_lock);
+ pthread_mutex_unlock(&e->lock);
- pthread_cond_destroy(&e->state_cond);
- pthread_mutex_destroy(&e->state_lock);
+ pthread_cond_destroy(&e->cond);
+ pthread_mutex_destroy(&e->lock);
if (e->apn != NULL)
free(e->apn);
@@ -164,39 +175,34 @@ void api_entry_del_name(struct api_entry * e,
}
}
-void api_entry_cancel(struct api_entry * e)
+int api_entry_sleep(struct api_entry * e,
+ struct timespec * timeo)
{
- pthread_mutex_lock(&e->state_lock);
-
- e->state = API_INIT;
- pthread_cond_broadcast(&e->state_cond);
-
- pthread_mutex_unlock(&e->state_lock);
-}
-
-int api_entry_sleep(struct api_entry * e)
-{
- struct timespec timeout = {(ENTRY_SLEEP_TIMEOUT / 1000),
- (ENTRY_SLEEP_TIMEOUT % 1000) * MILLION};
- struct timespec now;
struct timespec dl;
int ret = 0;
assert(e);
- clock_gettime(PTHREAD_COND_CLOCK, &now);
- ts_add(&now, &timeout, &dl);
+ if (timeo != NULL) {
+ clock_gettime(PTHREAD_COND_CLOCK, &dl);
+ ts_add(&dl, timeo, &dl);
+ }
- pthread_mutex_lock(&e->state_lock);
+ pthread_mutex_lock(&e->lock);
if (e->state != API_WAKE && e->state != API_DESTROY)
e->state = API_SLEEP;
+ pthread_cleanup_push(cancel_api_entry, e);
+
while (e->state == API_SLEEP && ret != -ETIMEDOUT)
- ret = -pthread_cond_timedwait(&e->state_cond,
- &e->state_lock,
- &dl);
+ if (timeo)
+ ret = -pthread_cond_timedwait(&e->cond, &e->lock, &dl);
+ else
+ ret = -pthread_cond_wait(&e->cond, &e->lock);
+
+ pthread_cleanup_pop(false);
if (e->state == API_DESTROY) {
if (e->re != NULL)
@@ -204,11 +210,10 @@ int api_entry_sleep(struct api_entry * e)
ret = -1;
}
- if (ret != -ETIMEDOUT)
- e->state = API_INIT;
+ e->state = API_INIT;
- pthread_cond_broadcast(&e->state_cond);
- pthread_mutex_unlock(&e->state_lock);
+ pthread_cond_broadcast(&e->cond);
+ pthread_mutex_unlock(&e->lock);
return ret;
}
@@ -219,25 +224,29 @@ void api_entry_wake(struct api_entry * e,
assert(e);
assert(re);
- pthread_mutex_lock(&e->state_lock);
+ pthread_mutex_lock(&e->lock);
if (e->state != API_SLEEP) {
- pthread_mutex_unlock(&e->state_lock);
+ pthread_mutex_unlock(&e->lock);
return;
}
e->state = API_WAKE;
e->re = re;
- pthread_cond_broadcast(&e->state_cond);
+ pthread_cond_broadcast(&e->cond);
+
+ pthread_cleanup_push(cancel_api_entry, e);
while (e->state == API_WAKE)
- pthread_cond_wait(&e->state_cond, &e->state_lock);
+ pthread_cond_wait(&e->cond, &e->lock);
+
+ pthread_cleanup_pop(false);
if (e->state == API_DESTROY)
e->state = API_INIT;
- pthread_mutex_unlock(&e->state_lock);
+ pthread_mutex_unlock(&e->lock);
}
int api_table_add(struct list_head * api_table,