#include "replace.h"
#include "system/filesys.h"
+#include "system/threads.h"
#include "pthreadpool_tevent.h"
#include "pthreadpool.h"
#include "lib/util/tevent_unix.h"
struct pthreadpool_tevent {
struct pthreadpool *pool;
struct pthreadpool_tevent_glue *glue_list;
+ /*
+ * Control access to the glue_list
+ */
+ pthread_mutex_t glue_mutex;
struct pthreadpool_tevent_job_state *jobs;
};
return ret;
}
+ ret = pthread_mutex_init(&pool->glue_mutex, NULL);
+ if (ret != 0) {
+ TALLOC_FREE(pool);
+ return ret;
+ }
+
talloc_set_destructor(pool, pthreadpool_tevent_destructor);
*presult = pool;
state->pool = NULL;
}
+ ret = pthread_mutex_lock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+
/*
* Delete all the registered
* tevent_context/tevent_threaded_context
/* The glue destructor removes it from the list */
TALLOC_FREE(glue);
}
+
+ pthread_mutex_unlock(&pool->glue_mutex);
+ pthread_mutex_destroy(&pool->glue_mutex);
+
pool->glue_list = NULL;
ret = pthreadpool_destroy(pool->pool);
return 0;
}
+/*
+ * glue destruction is only called with
+ * glue_mutex already locked either from
+ * a) pthreadpool_tevent_destructor or
+ * b) pthreadpool_tevent_glue_link_destructor
+ * pthreadpool_tevent_destructor accesses
+ * the glue_list while calling pthreadpool_tevent_glue_destructor
+ * which modifies the glue_list so it needs the lock held while
+ * doing that.
+ */
static int pthreadpool_tevent_glue_destructor(
struct pthreadpool_tevent_glue *glue)
{
static int pthreadpool_tevent_glue_link_destructor(
struct pthreadpool_tevent_glue_ev_link *ev_link)
{
- TALLOC_FREE(ev_link->glue);
+ if (ev_link->glue) {
+ int ret;
+ /* save the mutex */
+ pthread_mutex_t *glue_mutex =
+ &ev_link->glue->pool->glue_mutex;
+ ret = pthread_mutex_lock(glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+ TALLOC_FREE(ev_link->glue);
+ ret = pthread_mutex_unlock(glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+ }
return 0;
}
{
struct pthreadpool_tevent_glue *glue = NULL;
struct pthreadpool_tevent_glue_ev_link *ev_link = NULL;
+ int ret;
+ ret = pthread_mutex_lock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
/*
* See if this tevent_context was already registered by
* searching the glue object list. If so we have nothing
*/
for (glue = pool->glue_list; glue != NULL; glue = glue->next) {
if (glue->ev == ev) {
+ ret = pthread_mutex_unlock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
return 0;
}
}
+ ret = pthread_mutex_unlock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
/*
* Event context not yet registered - create a new glue
* object containing a tevent_context/tevent_threaded_context
}
#endif
+ ret = pthread_mutex_lock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+
DLIST_ADD(pool->glue_list, glue);
+
+ ret = pthread_mutex_unlock(&pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
return 0;
}
job_private_data, struct pthreadpool_tevent_job_state);
struct tevent_threaded_context *tctx = NULL;
struct pthreadpool_tevent_glue *g = NULL;
+ int ret;
if (state->pool == NULL) {
/* The pthreadpool_tevent is already gone */
}
#ifdef HAVE_PTHREAD
+ ret = pthread_mutex_lock(&state->pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+
for (g = state->pool->glue_list; g != NULL; g = g->next) {
if (g->ev == state->ev) {
tctx = g->tctx;
}
}
+ ret = pthread_mutex_unlock(&state->pool->glue_mutex);
+ if (ret != 0) {
+ return ret;
+ }
+
if (tctx == NULL) {
abort();
}