1*549b59edSchristos /* $NetBSD: libevent_support.c,v 1.2 2021/08/14 16:14:58 christos Exp $ */
2e670fd5cSchristos
3e670fd5cSchristos /* libevent_support.c - routines to bridge libldap and libevent */
4e670fd5cSchristos /* $OpenLDAP$ */
5e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6e670fd5cSchristos *
7e670fd5cSchristos * Copyright 2017-2021 The OpenLDAP Foundation.
8e670fd5cSchristos * All rights reserved.
9e670fd5cSchristos *
10e670fd5cSchristos * Redistribution and use in source and binary forms, with or without
11e670fd5cSchristos * modification, are permitted only as authorized by the OpenLDAP
12e670fd5cSchristos * Public License.
13e670fd5cSchristos *
14e670fd5cSchristos * A copy of this license is available in the file LICENSE in the
15e670fd5cSchristos * top-level directory of the distribution or, alternatively, at
16e670fd5cSchristos * <http://www.OpenLDAP.org/license.html>.
17e670fd5cSchristos */
18e670fd5cSchristos
19e670fd5cSchristos #include <sys/cdefs.h>
20*549b59edSchristos __RCSID("$NetBSD: libevent_support.c,v 1.2 2021/08/14 16:14:58 christos Exp $");
21e670fd5cSchristos
22e670fd5cSchristos #include "portable.h"
23e670fd5cSchristos
24e670fd5cSchristos #include <ac/time.h>
25e670fd5cSchristos
26e670fd5cSchristos #include <event2/event.h>
27e670fd5cSchristos #include <event2/thread.h>
28e670fd5cSchristos
29e670fd5cSchristos #include "lload.h"
30e670fd5cSchristos #include "ldap_pvt_thread.h"
31e670fd5cSchristos
32e670fd5cSchristos static void *
lload_libevent_mutex_init(unsigned locktype)33e670fd5cSchristos lload_libevent_mutex_init( unsigned locktype )
34e670fd5cSchristos {
35e670fd5cSchristos int rc;
36e670fd5cSchristos ldap_pvt_thread_mutex_t *mutex =
37e670fd5cSchristos ch_malloc( sizeof(ldap_pvt_thread_mutex_t) );
38e670fd5cSchristos
39e670fd5cSchristos if ( locktype & EVTHREAD_LOCKTYPE_RECURSIVE ) {
40e670fd5cSchristos rc = ldap_pvt_thread_mutex_recursive_init( mutex );
41e670fd5cSchristos } else {
42e670fd5cSchristos rc = ldap_pvt_thread_mutex_init( mutex );
43e670fd5cSchristos }
44e670fd5cSchristos if ( rc ) {
45e670fd5cSchristos ch_free( mutex );
46e670fd5cSchristos mutex = NULL;
47e670fd5cSchristos }
48e670fd5cSchristos return mutex;
49e670fd5cSchristos }
50e670fd5cSchristos
51e670fd5cSchristos static void
lload_libevent_mutex_destroy(void * lock,unsigned locktype)52e670fd5cSchristos lload_libevent_mutex_destroy( void *lock, unsigned locktype )
53e670fd5cSchristos {
54e670fd5cSchristos int rc;
55e670fd5cSchristos ldap_pvt_thread_mutex_t *mutex = lock;
56e670fd5cSchristos
57e670fd5cSchristos rc = ldap_pvt_thread_mutex_destroy( mutex );
58e670fd5cSchristos assert( rc == 0 );
59e670fd5cSchristos ch_free( mutex );
60e670fd5cSchristos }
61e670fd5cSchristos
62e670fd5cSchristos static int
lload_libevent_mutex_lock(unsigned mode,void * lock)63e670fd5cSchristos lload_libevent_mutex_lock( unsigned mode, void *lock )
64e670fd5cSchristos {
65e670fd5cSchristos ldap_pvt_thread_mutex_t *mutex = lock;
66e670fd5cSchristos
67e670fd5cSchristos if ( mode & EVTHREAD_TRY ) {
68e670fd5cSchristos return ldap_pvt_thread_mutex_trylock( mutex );
69e670fd5cSchristos } else {
70e670fd5cSchristos return ldap_pvt_thread_mutex_lock( mutex );
71e670fd5cSchristos }
72e670fd5cSchristos }
73e670fd5cSchristos
74e670fd5cSchristos static int
lload_libevent_mutex_unlock(unsigned mode,void * lock)75e670fd5cSchristos lload_libevent_mutex_unlock( unsigned mode, void *lock )
76e670fd5cSchristos {
77e670fd5cSchristos ldap_pvt_thread_mutex_t *mutex = lock;
78e670fd5cSchristos
79e670fd5cSchristos return ldap_pvt_thread_mutex_unlock( mutex );
80e670fd5cSchristos }
81e670fd5cSchristos
82e670fd5cSchristos static void *
lload_libevent_cond_init(unsigned condtype)83e670fd5cSchristos lload_libevent_cond_init( unsigned condtype )
84e670fd5cSchristos {
85e670fd5cSchristos int rc;
86e670fd5cSchristos ldap_pvt_thread_cond_t *cond =
87e670fd5cSchristos ch_malloc( sizeof(ldap_pvt_thread_cond_t) );
88e670fd5cSchristos
89e670fd5cSchristos assert( condtype == 0 );
90e670fd5cSchristos rc = ldap_pvt_thread_cond_init( cond );
91e670fd5cSchristos if ( rc ) {
92e670fd5cSchristos ch_free( cond );
93e670fd5cSchristos cond = NULL;
94e670fd5cSchristos }
95e670fd5cSchristos return cond;
96e670fd5cSchristos }
97e670fd5cSchristos
98e670fd5cSchristos static void
lload_libevent_cond_destroy(void * c)99e670fd5cSchristos lload_libevent_cond_destroy( void *c )
100e670fd5cSchristos {
101e670fd5cSchristos int rc;
102e670fd5cSchristos ldap_pvt_thread_cond_t *cond = c;
103e670fd5cSchristos
104e670fd5cSchristos rc = ldap_pvt_thread_cond_destroy( cond );
105e670fd5cSchristos assert( rc == 0 );
106e670fd5cSchristos ch_free( c );
107e670fd5cSchristos }
108e670fd5cSchristos
109e670fd5cSchristos static int
lload_libevent_cond_signal(void * c,int broadcast)110e670fd5cSchristos lload_libevent_cond_signal( void *c, int broadcast )
111e670fd5cSchristos {
112e670fd5cSchristos ldap_pvt_thread_cond_t *cond = c;
113e670fd5cSchristos
114e670fd5cSchristos if ( broadcast ) {
115e670fd5cSchristos return ldap_pvt_thread_cond_broadcast( cond );
116e670fd5cSchristos } else {
117e670fd5cSchristos return ldap_pvt_thread_cond_signal( cond );
118e670fd5cSchristos }
119e670fd5cSchristos }
120e670fd5cSchristos
121e670fd5cSchristos static int
lload_libevent_cond_timedwait(void * c,void * lock,const struct timeval * timeout)122e670fd5cSchristos lload_libevent_cond_timedwait(
123e670fd5cSchristos void *c,
124e670fd5cSchristos void *lock,
125e670fd5cSchristos const struct timeval *timeout )
126e670fd5cSchristos {
127e670fd5cSchristos ldap_pvt_thread_cond_t *cond = c;
128e670fd5cSchristos ldap_pvt_thread_mutex_t *mutex = lock;
129e670fd5cSchristos
130e670fd5cSchristos /*
131e670fd5cSchristos * libevent does not seem to request a timeout, this is true as of 2.1.8
132e670fd5cSchristos * that has just been marked the first stable release of the 2.1 series
133e670fd5cSchristos */
134e670fd5cSchristos assert( timeout == NULL );
135e670fd5cSchristos
136e670fd5cSchristos return ldap_pvt_thread_cond_wait( cond, mutex );
137e670fd5cSchristos }
138e670fd5cSchristos
139e670fd5cSchristos int
lload_libevent_init(void)140e670fd5cSchristos lload_libevent_init( void )
141e670fd5cSchristos {
142e670fd5cSchristos struct evthread_lock_callbacks cbs = {
143e670fd5cSchristos EVTHREAD_LOCK_API_VERSION,
144e670fd5cSchristos EVTHREAD_LOCKTYPE_RECURSIVE,
145e670fd5cSchristos lload_libevent_mutex_init,
146e670fd5cSchristos lload_libevent_mutex_destroy,
147e670fd5cSchristos lload_libevent_mutex_lock,
148e670fd5cSchristos lload_libevent_mutex_unlock
149e670fd5cSchristos };
150e670fd5cSchristos struct evthread_condition_callbacks cond_cbs = {
151e670fd5cSchristos EVTHREAD_CONDITION_API_VERSION,
152e670fd5cSchristos lload_libevent_cond_init,
153e670fd5cSchristos lload_libevent_cond_destroy,
154e670fd5cSchristos lload_libevent_cond_signal,
155e670fd5cSchristos lload_libevent_cond_timedwait
156e670fd5cSchristos };
157e670fd5cSchristos
158e670fd5cSchristos #ifndef BALANCER_MODULE
159e670fd5cSchristos /* only necessary if lload is a server, slapd already calls
160e670fd5cSchristos * ldap_pvt_thread_initialize() */
161e670fd5cSchristos if ( ldap_pvt_thread_initialize() ) {
162e670fd5cSchristos return -1;
163e670fd5cSchristos }
164e670fd5cSchristos #endif
165e670fd5cSchristos
166e670fd5cSchristos evthread_set_lock_callbacks( &cbs );
167e670fd5cSchristos evthread_set_condition_callbacks( &cond_cbs );
168e670fd5cSchristos evthread_set_id_callback( ldap_pvt_thread_self );
169e670fd5cSchristos return 0;
170e670fd5cSchristos }
171e670fd5cSchristos
172e670fd5cSchristos void
lload_libevent_destroy(void)173e670fd5cSchristos lload_libevent_destroy( void )
174e670fd5cSchristos {
175e670fd5cSchristos libevent_global_shutdown();
176e670fd5cSchristos }
177