1 /*
2   This file is part of libmicrohttpd
3   Copyright (C) 2016 Karlson2k (Evgeny Grin)
4 
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9 
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14 
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 
19 */
20 
21 /**
22  * @file microhttpd/mhd_locks.h
23  * @brief  Header for platform-independent locks abstraction
24  * @author Karlson2k (Evgeny Grin)
25  * @author Christian Grothoff
26  *
27  * Provides basic abstraction for locks/mutex.
28  * Any functions can be implemented as macro on some platforms
29  * unless explicitly marked otherwise.
30  * Any function argument can be skipped in macro, so avoid
31  * variable modification in function parameters.
32  *
33  * @warning Unlike pthread functions, most of functions return
34  *          nonzero on success.
35  */
36 
37 #ifndef MHD_LOCKS_H
38 #define MHD_LOCKS_H 1
39 
40 #include "mhd_options.h"
41 
42 #ifdef MHD_USE_THREADS
43 
44 #if defined(MHD_USE_W32_THREADS)
45 #  define MHD_W32_MUTEX_ 1
46 #  ifndef WIN32_LEAN_AND_MEAN
47 #    define WIN32_LEAN_AND_MEAN 1
48 #  endif /* !WIN32_LEAN_AND_MEAN */
49 #  include <windows.h>
50 #elif defined(HAVE_PTHREAD_H) && defined(MHD_USE_POSIX_THREADS)
51 #  define MHD_PTHREAD_MUTEX_ 1
52 #  undef HAVE_CONFIG_H
53 #  include <pthread.h>
54 #  define HAVE_CONFIG_H 1
55 #else
56 #  error No base mutex API is available.
57 #endif
58 
59 #ifndef MHD_PANIC
60 #  include <stdio.h>
61 #  ifdef HAVE_STDLIB_H
62 #    include <stdlib.h>
63 #  endif /* HAVE_STDLIB_H */
64 /* Simple implementation of MHD_PANIC, to be used outside lib */
65 #  define MHD_PANIC(msg) do { fprintf (stderr,           \
66                                        "Abnormal termination at %d line in file %s: %s\n", \
67                                        (int) __LINE__, __FILE__, msg); abort (); \
68 } while (0)
69 #endif /* ! MHD_PANIC */
70 
71 #if defined(MHD_PTHREAD_MUTEX_)
72 typedef pthread_mutex_t MHD_mutex_;
73 #elif defined(MHD_W32_MUTEX_)
74 typedef CRITICAL_SECTION MHD_mutex_;
75 #endif
76 
77 #if defined(MHD_PTHREAD_MUTEX_)
78 /**
79  * Initialise new mutex.
80  * @param pmutex pointer to the mutex
81  * @return nonzero on success, zero otherwise
82  */
83 #define MHD_mutex_init_(pmutex) (! (pthread_mutex_init ((pmutex), NULL)))
84 #elif defined(MHD_W32_MUTEX_)
85 /**
86  * Initialise new mutex.
87  * @param pmutex pointer to mutex
88  * @return nonzero on success, zero otherwise
89  */
90 #define MHD_mutex_init_(pmutex) (InitializeCriticalSectionAndSpinCount ( \
91                                    (pmutex),16))
92 #endif
93 
94 #if defined(MHD_PTHREAD_MUTEX_)
95 #  if defined(PTHREAD_MUTEX_INITIALIZER)
96 /**
97  *  Define static mutex and statically initialise it.
98  */
99 #    define MHD_MUTEX_STATIC_DEFN_INIT_(m) static MHD_mutex_ m = \
100   PTHREAD_MUTEX_INITIALIZER
101 #  endif /* PTHREAD_MUTEX_INITIALIZER */
102 #endif
103 
104 #if defined(MHD_PTHREAD_MUTEX_)
105 /**
106  * Destroy previously initialised mutex.
107  * @param pmutex pointer to mutex
108  * @return nonzero on success, zero otherwise
109  */
110 #define MHD_mutex_destroy_(pmutex) (! (pthread_mutex_destroy ((pmutex))))
111 #elif defined(MHD_W32_MUTEX_)
112 /**
113  * Destroy previously initialised mutex.
114  * @param pmutex pointer to mutex
115  * @return Always nonzero
116  */
117 #define MHD_mutex_destroy_(pmutex) (DeleteCriticalSection ((pmutex)), ! 0)
118 #endif
119 
120 /**
121  * Destroy previously initialised mutex and abort execution
122  * if error is detected.
123  * @param pmutex pointer to mutex
124  */
125 #define MHD_mutex_destroy_chk_(pmutex) do {       \
126     if (! MHD_mutex_destroy_ (pmutex))              \
127       MHD_PANIC (_ ("Failed to destroy mutex.\n")); \
128 } while (0)
129 
130 
131 #if defined(MHD_PTHREAD_MUTEX_)
132 /**
133  * Acquire lock on previously initialised mutex.
134  * If mutex was already locked by other thread, function
135  * blocks until mutex becomes available.
136  * @param pmutex pointer to mutex
137  * @return nonzero on success, zero otherwise
138  */
139 #define MHD_mutex_lock_(pmutex) (! (pthread_mutex_lock ((pmutex))))
140 #elif defined(MHD_W32_MUTEX_)
141 /**
142  * Acquire lock on previously initialised mutex.
143  * If mutex was already locked by other thread, function
144  * blocks until mutex becomes available.
145  * @param pmutex pointer to mutex
146  * @return Always nonzero
147  */
148 #define MHD_mutex_lock_(pmutex) (EnterCriticalSection ((pmutex)), ! 0)
149 #endif
150 
151 /**
152  * Acquire lock on previously initialised mutex.
153  * If mutex was already locked by other thread, function
154  * blocks until mutex becomes available.
155  * If error is detected, execution will be aborted.
156  * @param pmutex pointer to mutex
157  */
158 #define MHD_mutex_lock_chk_(pmutex) do {       \
159     if (! MHD_mutex_lock_ (pmutex))              \
160       MHD_PANIC (_ ("Failed to lock mutex.\n")); \
161 } while (0)
162 
163 #if defined(MHD_PTHREAD_MUTEX_)
164 /**
165  * Unlock previously initialised and locked mutex.
166  * @param pmutex pointer to mutex
167  * @return nonzero on success, zero otherwise
168  */
169 #define MHD_mutex_unlock_(pmutex) (! (pthread_mutex_unlock ((pmutex))))
170 #elif defined(MHD_W32_MUTEX_)
171 /**
172  * Unlock previously initialised and locked mutex.
173  * @param pmutex pointer to mutex
174  * @return Always nonzero
175  */
176 #define MHD_mutex_unlock_(pmutex) (LeaveCriticalSection ((pmutex)), ! 0)
177 #endif
178 
179 /**
180  * Unlock previously initialised and locked mutex.
181  * If error is detected, execution will be aborted.
182  * @param pmutex pointer to mutex
183  */
184 #define MHD_mutex_unlock_chk_(pmutex) do {       \
185     if (! MHD_mutex_unlock_ (pmutex))              \
186       MHD_PANIC (_ ("Failed to unlock mutex.\n")); \
187 } while (0)
188 
189 #else  /* ! MHD_USE_THREADS */
190 
191 #define MHD_mutex_init_(ignore) (! 0)
192 #define MHD_mutex_destroy_(ignore) (! 0)
193 #define MHD_mutex_destroy_chk_(ignore) (void)0
194 #define MHD_mutex_lock_(ignore) (! 0)
195 #define MHD_mutex_lock_chk_(ignore) (void)0
196 #define MHD_mutex_unlock_(ignore) (! 0)
197 #define MHD_mutex_unlock_chk_(ignore) (void)0
198 
199 #endif /* ! MHD_USE_THREADS */
200 
201 #endif /* ! MHD_LOCKS_H */
202