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 * 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 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 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 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 * 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 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 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 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 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 173 lload_libevent_destroy( void ) 174 { 175 libevent_global_shutdown(); 176 } 177