xref: /netbsd-src/external/bsd/openldap/dist/servers/lloadd/libevent_support.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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