summaryrefslogtreecommitdiff
path: root/usr/src/cmd/idmap/idmapd/adutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/idmap/idmapd/adutils.c')
-rw-r--r--usr/src/cmd/idmap/idmapd/adutils.c62
1 files changed, 57 insertions, 5 deletions
diff --git a/usr/src/cmd/idmap/idmapd/adutils.c b/usr/src/cmd/idmap/idmapd/adutils.c
index 279179e13b..4cfa56e073 100644
--- a/usr/src/cmd/idmap/idmapd/adutils.c
+++ b/usr/src/cmd/idmap/idmapd/adutils.c
@@ -139,6 +139,8 @@ typedef struct idmap_q {
struct idmap_query_state {
idmap_query_state_t *next;
int qcount; /* how many queries */
+ int ref_cnt; /* reference count */
+ pthread_cond_t cv; /* Condition wait variable */
uint32_t qlastsent;
uint32_t qinflight; /* how many queries in flight */
uint16_t qdead; /* oops, lost LDAP connection */
@@ -162,6 +164,12 @@ static ad_host_t *host_head = NULL;
static pthread_t reaperid = 0;
static pthread_mutex_t adhostlock = PTHREAD_MUTEX_INITIALIZER;
+
+static void
+idmap_lookup_unlock_batch(idmap_query_state_t **state);
+
+
+
/*ARGSUSED*/
static int
idmap_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) {
@@ -943,11 +951,13 @@ idmap_lookup_batch_start(ad_t *ad, int nqueries, idmap_query_state_t **state)
if (new_state == NULL)
return (IDMAP_ERR_MEMORY);
+ new_state->ref_cnt = 1;
new_state->qadh = adh;
new_state->qcount = nqueries;
new_state->qadh_gen = adh->generation;
/* should be -1, but the atomic routines want unsigned */
new_state->qlastsent = 0;
+ (void) pthread_cond_init(&new_state->cv, NULL);
(void) pthread_mutex_lock(&qstatelock);
new_state->next = qstatehead;
@@ -961,7 +971,9 @@ idmap_lookup_batch_start(ad_t *ad, int nqueries, idmap_query_state_t **state)
/*
* Find the idmap_query_state_t to which a given LDAP result msgid on a
- * given connection belongs
+ * given connection belongs. This routine increaments the reference count
+ * so that the object can not be freed. idmap_lookup_unlock_batch()
+ * must be called to decreament the reference count.
*/
static
int
@@ -977,6 +989,7 @@ idmap_msgid2query(ad_host_t *adh, int msgid,
continue;
for (i = 0; i < p->qcount; i++) {
if ((p->queries[i]).msgid == msgid) {
+ p->ref_cnt++;
*state = p;
*qid = i;
(void) pthread_mutex_unlock(&qstatelock);
@@ -1215,6 +1228,7 @@ idmap_get_adobject_batch(ad_host_t *adh, struct timeval *timeout)
atomic_dec_32(&query_state->qinflight);
/* we saw at least one reply */
query_state->queries[qid].got_reply = 1;
+ idmap_lookup_unlock_batch(&query_state);
}
(void) ldap_msgfree(res);
ret = 0;
@@ -1238,6 +1252,7 @@ idmap_get_adobject_batch(ad_host_t *adh, struct timeval *timeout)
/* we saw at least one result */
query_state->queries[qid].got_reply = 1;
query_state->queries[qid].got_results = 1;
+ idmap_lookup_unlock_batch(&query_state);
}
(void) ldap_msgfree(res);
ret = 0;
@@ -1251,15 +1266,48 @@ idmap_get_adobject_batch(ad_host_t *adh, struct timeval *timeout)
return (ret);
}
+/*
+ * This routine decreament the reference count of the
+ * idmap_query_state_t
+ */
+static void
+idmap_lookup_unlock_batch(idmap_query_state_t **state)
+{
+ /*
+ * Decrement reference count with qstatelock locked
+ */
+ (void) pthread_mutex_lock(&qstatelock);
+ (*state)->ref_cnt--;
+ /*
+ * If there are no references wakup the allocating thread
+ */
+ if ((*state)->ref_cnt == 0)
+ (void) pthread_cond_signal(&(*state)->cv);
+ (void) pthread_mutex_unlock(&qstatelock);
+ *state = NULL;
+}
+
+/*
+ * This routine frees the idmap_query_state_t structure
+ * If the reference count is greater than 1 it waits
+ * for the other threads to finish using it.
+ */
void
-idmap_lookup_free_batch(idmap_query_state_t **state)
+idmap_lookup_release_batch(idmap_query_state_t **state)
{
idmap_query_state_t **p;
- idmap_release_conn((*state)->qadh);
+ /*
+ * Decrement reference count with qstatelock locked
+ * and wait for reference count to get to zero
+ */
+ (void) pthread_mutex_lock(&qstatelock);
+ (*state)->ref_cnt--;
+ while ((*state)->ref_cnt > 0) {
+ (void) pthread_cond_wait(&(*state)->cv, &qstatelock);
+ }
/* Remove this state struct from the list of state structs */
- (void) pthread_mutex_lock(&qstatelock);
for (p = &qstatehead; *p != NULL; p = &(*p)->next) {
if (*p == (*state)) {
*p = (*state)->next;
@@ -1268,6 +1316,10 @@ idmap_lookup_free_batch(idmap_query_state_t **state)
}
(void) pthread_mutex_unlock(&qstatelock);
+ (void) pthread_cond_destroy(&(*state)->cv);
+
+ idmap_release_conn((*state)->qadh);
+
free(*state);
*state = NULL;
}
@@ -1307,7 +1359,7 @@ idmap_lookup_batch_end(idmap_query_state_t **state,
}
}
- idmap_lookup_free_batch(state);
+ idmap_lookup_release_batch(state);
return (retcode);
}