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