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 #if defined(MHD_USE_W32_THREADS)
43 #  define MHD_W32_MUTEX_ 1
44 #  ifndef WIN32_LEAN_AND_MEAN
45 #    define WIN32_LEAN_AND_MEAN 1
46 #  endif /* !WIN32_LEAN_AND_MEAN */
47 #  include <windows.h>
48 #elif defined(HAVE_PTHREAD_H) && defined(MHD_USE_POSIX_THREADS)
49 #  define MHD_PTHREAD_MUTEX_ 1
50 #  undef HAVE_CONFIG_H
51 #  include <pthread.h>
52 #  define HAVE_CONFIG_H 1
53 #else
54 #  error No base mutex API is available.
55 #endif
56 
57 #ifndef MHD_PANIC
58 #  include <stdio.h>
59 #  include <stdlib.h>
60 /* Simple implementation of MHD_PANIC, to be used outside lib */
61 #  define MHD_PANIC(msg) do { fprintf (stderr,           \
62                                        "Abnormal termination at %d line in file %s: %s\n", \
63                                        (int) __LINE__, __FILE__, msg); abort (); \
64 } while (0)
65 #endif /* ! MHD_PANIC */
66 
67 #if defined(MHD_PTHREAD_MUTEX_)
68 typedef pthread_mutex_t MHD_mutex_;
69 #elif defined(MHD_W32_MUTEX_)
70 typedef CRITICAL_SECTION MHD_mutex_;
71 #endif
72 
73 #if defined(MHD_PTHREAD_MUTEX_)
74 /**
75  * Initialise new mutex.
76  * @param pmutex pointer to the mutex
77  * @return nonzero on success, zero otherwise
78  */
79 #define MHD_mutex_init_(pmutex) (! (pthread_mutex_init ((pmutex), NULL)))
80 #elif defined(MHD_W32_MUTEX_)
81 /**
82  * Initialise new mutex.
83  * @param pmutex pointer to mutex
84  * @return nonzero on success, zero otherwise
85  */
86 #define MHD_mutex_init_(pmutex) (InitializeCriticalSectionAndSpinCount ( \
87                                    (pmutex),16))
88 #endif
89 
90 #if defined(MHD_PTHREAD_MUTEX_)
91 #  if defined(PTHREAD_MUTEX_INITIALIZER)
92 /**
93  *  Define static mutex and statically initialise it.
94  */
95 #    define MHD_MUTEX_STATIC_DEFN_INIT_(m) static MHD_mutex_ m = \
96   PTHREAD_MUTEX_INITIALIZER
97 #  endif /* PTHREAD_MUTEX_INITIALIZER */
98 #endif
99 
100 #if defined(MHD_PTHREAD_MUTEX_)
101 /**
102  * Destroy previously initialised mutex.
103  * @param pmutex pointer to mutex
104  * @return nonzero on success, zero otherwise
105  */
106 #define MHD_mutex_destroy_(pmutex) (! (pthread_mutex_destroy ((pmutex))))
107 #elif defined(MHD_W32_MUTEX_)
108 /**
109  * Destroy previously initialised mutex.
110  * @param pmutex pointer to mutex
111  * @return Always nonzero
112  */
113 #define MHD_mutex_destroy_(pmutex) (DeleteCriticalSection ((pmutex)), ! 0)
114 #endif
115 
116 /**
117  * Destroy previously initialised mutex and abort execution
118  * if error is detected.
119  * @param pmutex pointer to mutex
120  */
121 #define MHD_mutex_destroy_chk_(pmutex) do {       \
122     if (! MHD_mutex_destroy_ (pmutex))              \
123       MHD_PANIC (_ ("Failed to destroy mutex.\n")); \
124 } while (0)
125 
126 
127 #if defined(MHD_PTHREAD_MUTEX_)
128 /**
129  * Acquire lock on previously initialised mutex.
130  * If mutex was already locked by other thread, function
131  * blocks until mutex becomes available.
132  * @param pmutex pointer to mutex
133  * @return nonzero on success, zero otherwise
134  */
135 #define MHD_mutex_lock_(pmutex) (! (pthread_mutex_lock ((pmutex))))
136 #elif defined(MHD_W32_MUTEX_)
137 /**
138  * Acquire lock on previously initialised mutex.
139  * If mutex was already locked by other thread, function
140  * blocks until mutex becomes available.
141  * @param pmutex pointer to mutex
142  * @return Always nonzero
143  */
144 #define MHD_mutex_lock_(pmutex) (EnterCriticalSection ((pmutex)), ! 0)
145 #endif
146 
147 /**
148  * Acquire lock on previously initialised mutex.
149  * If mutex was already locked by other thread, function
150  * blocks until mutex becomes available.
151  * If error is detected, execution will be aborted.
152  * @param pmutex pointer to mutex
153  */
154 #define MHD_mutex_lock_chk_(pmutex) do {       \
155     if (! MHD_mutex_lock_ (pmutex))              \
156       MHD_PANIC (_ ("Failed to lock mutex.\n")); \
157 } while (0)
158 
159 #if defined(MHD_PTHREAD_MUTEX_)
160 /**
161  * Unlock previously initialised and locked mutex.
162  * @param pmutex pointer to mutex
163  * @return nonzero on success, zero otherwise
164  */
165 #define MHD_mutex_unlock_(pmutex) (! (pthread_mutex_unlock ((pmutex))))
166 #elif defined(MHD_W32_MUTEX_)
167 /**
168  * Unlock previously initialised and locked mutex.
169  * @param pmutex pointer to mutex
170  * @return Always nonzero
171  */
172 #define MHD_mutex_unlock_(pmutex) (LeaveCriticalSection ((pmutex)), ! 0)
173 #endif
174 
175 /**
176  * Unlock previously initialised and locked mutex.
177  * If error is detected, execution will be aborted.
178  * @param pmutex pointer to mutex
179  */
180 #define MHD_mutex_unlock_chk_(pmutex) do {       \
181     if (! MHD_mutex_unlock_ (pmutex))              \
182       MHD_PANIC (_ ("Failed to unlock mutex.\n")); \
183 } while (0)
184 
185 
186 #endif /* ! MHD_LOCKS_H */
187