tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

evthread_pthread.c (4957B)


      1 /*
      2 * Copyright 2009-2012 Niels Provos and Nick Mathewson
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions
      6 * are met:
      7 * 1. Redistributions of source code must retain the above copyright
      8 *    notice, this list of conditions and the following disclaimer.
      9 * 2. Redistributions in binary form must reproduce the above copyright
     10 *    notice, this list of conditions and the following disclaimer in the
     11 *    documentation and/or other materials provided with the distribution.
     12 * 3. The name of the author may not be used to endorse or promote products
     13 *    derived from this software without specific prior written permission.
     14 *
     15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25 */
     26 #include "event2/event-config.h"
     27 #include "evconfig-private.h"
     28 
     29 /* With glibc we need to define _GNU_SOURCE to get PTHREAD_MUTEX_RECURSIVE.
     30 * This comes from evconfig-private.h
     31 */
     32 #include <pthread.h>
     33 
     34 struct event_base;
     35 #include "event2/thread.h"
     36 
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include "mm-internal.h"
     40 #include "evthread-internal.h"
     41 
     42 static pthread_mutexattr_t attr_recursive;
     43 
     44 static void *
     45 evthread_posix_lock_alloc(unsigned locktype)
     46 {
     47 pthread_mutexattr_t *attr = NULL;
     48 pthread_mutex_t *lock = mm_malloc(sizeof(pthread_mutex_t));
     49 if (!lock)
     50 	return NULL;
     51 if (locktype & EVTHREAD_LOCKTYPE_RECURSIVE)
     52 	attr = &attr_recursive;
     53 if (pthread_mutex_init(lock, attr)) {
     54 	mm_free(lock);
     55 	return NULL;
     56 }
     57 return lock;
     58 }
     59 
     60 static void
     61 evthread_posix_lock_free(void *lock_, unsigned locktype)
     62 {
     63 pthread_mutex_t *lock = lock_;
     64 pthread_mutex_destroy(lock);
     65 mm_free(lock);
     66 }
     67 
     68 static int
     69 evthread_posix_lock(unsigned mode, void *lock_)
     70 {
     71 pthread_mutex_t *lock = lock_;
     72 if (mode & EVTHREAD_TRY)
     73 	return pthread_mutex_trylock(lock);
     74 else
     75 	return pthread_mutex_lock(lock);
     76 }
     77 
     78 static int
     79 evthread_posix_unlock(unsigned mode, void *lock_)
     80 {
     81 pthread_mutex_t *lock = lock_;
     82 return pthread_mutex_unlock(lock);
     83 }
     84 
     85 static unsigned long
     86 evthread_posix_get_id(void)
     87 {
     88 union {
     89 	pthread_t thr;
     90 #if EVENT__SIZEOF_PTHREAD_T > EVENT__SIZEOF_LONG
     91 	ev_uint64_t id;
     92 #else
     93 	unsigned long id;
     94 #endif
     95 } r;
     96 #if EVENT__SIZEOF_PTHREAD_T < EVENT__SIZEOF_LONG
     97 memset(&r, 0, sizeof(r));
     98 #endif
     99 r.thr = pthread_self();
    100 return (unsigned long)r.id;
    101 }
    102 
    103 static void *
    104 evthread_posix_cond_alloc(unsigned condflags)
    105 {
    106 pthread_cond_t *cond = mm_malloc(sizeof(pthread_cond_t));
    107 if (!cond)
    108 	return NULL;
    109 if (pthread_cond_init(cond, NULL)) {
    110 	mm_free(cond);
    111 	return NULL;
    112 }
    113 return cond;
    114 }
    115 
    116 static void
    117 evthread_posix_cond_free(void *cond_)
    118 {
    119 pthread_cond_t *cond = cond_;
    120 pthread_cond_destroy(cond);
    121 mm_free(cond);
    122 }
    123 
    124 static int
    125 evthread_posix_cond_signal(void *cond_, int broadcast)
    126 {
    127 pthread_cond_t *cond = cond_;
    128 int r;
    129 if (broadcast)
    130 	r = pthread_cond_broadcast(cond);
    131 else
    132 	r = pthread_cond_signal(cond);
    133 return r ? -1 : 0;
    134 }
    135 
    136 static int
    137 evthread_posix_cond_wait(void *cond_, void *lock_, const struct timeval *tv)
    138 {
    139 int r;
    140 pthread_cond_t *cond = cond_;
    141 pthread_mutex_t *lock = lock_;
    142 
    143 if (tv) {
    144 	struct timeval now, abstime;
    145 	struct timespec ts;
    146 	evutil_gettimeofday(&now, NULL);
    147 	evutil_timeradd(&now, tv, &abstime);
    148 	ts.tv_sec = abstime.tv_sec;
    149 	ts.tv_nsec = abstime.tv_usec*1000;
    150 	r = pthread_cond_timedwait(cond, lock, &ts);
    151 	if (r == ETIMEDOUT)
    152 		return 1;
    153 	else if (r)
    154 		return -1;
    155 	else
    156 		return 0;
    157 } else {
    158 	r = pthread_cond_wait(cond, lock);
    159 	return r ? -1 : 0;
    160 }
    161 }
    162 
    163 int
    164 evthread_use_pthreads(void)
    165 {
    166 struct evthread_lock_callbacks cbs = {
    167 	EVTHREAD_LOCK_API_VERSION,
    168 	EVTHREAD_LOCKTYPE_RECURSIVE,
    169 	evthread_posix_lock_alloc,
    170 	evthread_posix_lock_free,
    171 	evthread_posix_lock,
    172 	evthread_posix_unlock
    173 };
    174 struct evthread_condition_callbacks cond_cbs = {
    175 	EVTHREAD_CONDITION_API_VERSION,
    176 	evthread_posix_cond_alloc,
    177 	evthread_posix_cond_free,
    178 	evthread_posix_cond_signal,
    179 	evthread_posix_cond_wait
    180 };
    181 /* Set ourselves up to get recursive locks. */
    182 if (pthread_mutexattr_init(&attr_recursive))
    183 	return -1;
    184 if (pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE))
    185 	return -1;
    186 
    187 evthread_set_lock_callbacks(&cbs);
    188 evthread_set_condition_callbacks(&cond_cbs);
    189 evthread_set_id_callback(evthread_posix_get_id);
    190 return 0;
    191 }