00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <string.h>
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #include <errno.h>
00062 #include <unistd.h>
00063
00064 #include "gwlib/gwlib.h"
00065
00066
00067 #ifdef MUTEX_STATS
00068 Mutex *mutex_make_measured(Mutex *mutex, unsigned char *filename, int lineno)
00069 {
00070 mutex->filename = filename;
00071 mutex->lineno = lineno;
00072 mutex->locks = 0;
00073 mutex->collisions = 0;
00074 return mutex;
00075 }
00076 #endif
00077
00078 Mutex *mutex_create_real(void)
00079 {
00080 Mutex *mutex;
00081
00082 mutex = gw_malloc(sizeof(Mutex));
00083 pthread_mutex_init(&mutex->mutex, NULL);
00084 mutex->owner = -1;
00085 mutex->dynamic = 1;
00086 return mutex;
00087 }
00088
00089 Mutex *mutex_init_static_real(Mutex *mutex)
00090 {
00091 pthread_mutex_init(&mutex->mutex, NULL);
00092 mutex->owner = -1;
00093 mutex->dynamic = 0;
00094 return mutex;
00095 }
00096
00097 void mutex_destroy(Mutex *mutex)
00098 {
00099 int ret;
00100
00101 if (mutex == NULL)
00102 return;
00103
00104 #ifdef MUTEX_STATS
00105 if (mutex->locks > 0 || mutex->collisions > 0) {
00106 info(0, "Mutex %s:%d: %ld locks, %ld collisions.",
00107 mutex->filename, mutex->lineno,
00108 mutex->locks, mutex->collisions);
00109 }
00110 #endif
00111
00112 if ((ret = pthread_mutex_destroy(&mutex->mutex)) != 0)
00113 panic(ret, "Attempt to destroy locked mutex!");
00114
00115 if (mutex->dynamic == 0)
00116 return;
00117 gw_free(mutex);
00118 }
00119
00120
00121 void mutex_lock_real(Mutex *mutex, char *file, int line, const char *func)
00122 {
00123 int ret;
00124
00125 gw_assert(mutex != NULL);
00126
00127 #ifdef MUTEX_STATS
00128 ret = pthread_mutex_trylock(&mutex->mutex);
00129 if (ret != 0) {
00130 ret = pthread_mutex_lock(&mutex->mutex);
00131 mutex->collisions++;
00132 }
00133 mutex->locks++;
00134 #else
00135 ret = pthread_mutex_lock(&mutex->mutex);
00136 #endif
00137 if (ret != 0)
00138 panic(0, "%s:%ld: %s: Mutex failure! (Called from %s:%ld:%s.)", \
00139 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00140 if (mutex->owner == gwthread_self())
00141 panic(0, "%s:%ld: %s: Managed to lock the mutex twice! (Called from %s:%ld:%s.)", \
00142 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00143 mutex->owner = gwthread_self();
00144 }
00145
00146 int mutex_unlock_real(Mutex *mutex, char *file, int line, const char *func)
00147 {
00148 int ret;
00149
00150 if (mutex == NULL) {
00151 error(0, "%s:%ld: %s: Trying to unlock a NULL mutex! (Called from %s:%ld:%s.)", \
00152 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00153 return -1;
00154 }
00155 gw_assert(mutex != NULL);
00156 mutex->owner = -1;
00157 ret = pthread_mutex_unlock(&mutex->mutex);
00158 if (ret != 0)
00159 panic(0, "%s:%ld: %s: Mutex failure! (Called from %s:%ld:%s.)", \
00160 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00161
00162 return ret;
00163 }
00164
00165 int mutex_trylock_real(Mutex *mutex, const char *file, int line, const char *func)
00166 {
00167 int ret;
00168
00169 if (mutex == NULL) {
00170 error(0, "%s:%ld: %s: Trying to lock a NULL mutex! (Called from %s:%ld:%s.)", \
00171 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00172 return -1;
00173 }
00174
00175 ret = pthread_mutex_trylock(&mutex->mutex);
00176 if (ret == 0) {
00177 if (mutex->owner == gwthread_self())
00178 panic(0, "%s:%ld: %s: Managed to lock the mutex twice! (Called from %s:%ld:%s.)", \
00179 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00180
00181 mutex->owner = gwthread_self();
00182 }
00183 else if (ret == EINVAL)
00184 panic(0, "%s:%ld: %s: Mutex failure! (Called from %s:%ld:%s.)", \
00185 __FILE__, (long) __LINE__, __func__, file, (long) line, func);
00186
00187 return ret;
00188 }
00189
00190
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.