215 lines
4.6 KiB
C
215 lines
4.6 KiB
C
|
#define _GNU_SOURCE
|
||
|
|
||
|
#include <lladd/common.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <malloc.h>
|
||
|
|
||
|
#undef pthread_mutex_t
|
||
|
|
||
|
#undef pthread_mutex_init
|
||
|
#undef pthread_mutex_destroy
|
||
|
#undef pthread_mutex_lock
|
||
|
#undef pthread_mutex_trylock
|
||
|
#undef pthread_mutex_unlock
|
||
|
|
||
|
|
||
|
int __lladd_pthread_mutex_init(lladd_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr,
|
||
|
const char * file, int line, const char * name) {
|
||
|
|
||
|
mutex->file = file;
|
||
|
mutex->line = line;
|
||
|
mutex->name = name;
|
||
|
|
||
|
init_tuple(&(mutex->tup));
|
||
|
|
||
|
mutex->lockpoints = pblHtCreate();
|
||
|
|
||
|
return pthread_mutex_init(&(mutex->mutex), mutexattr);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
int __lladd_pthread_mutex_lock(lladd_pthread_mutex_t *mutex, char * file, int line) {
|
||
|
long blockCount = 0;
|
||
|
int ret;
|
||
|
char * location;
|
||
|
int location_length = asprintf(&location, "%s %d", file, line);
|
||
|
|
||
|
while(EBUSY == (ret = pthread_mutex_trylock(&(mutex->mutex)))) {
|
||
|
blockCount ++;
|
||
|
pthread_yield();
|
||
|
}
|
||
|
|
||
|
|
||
|
profile_tuple * tup = pblHtLookup(mutex->lockpoints, location, location_length+1);
|
||
|
|
||
|
mutex->last_acquired_at = location;
|
||
|
|
||
|
if(!tup) {
|
||
|
tup = malloc(sizeof(profile_tuple));
|
||
|
|
||
|
init_tuple(tup);
|
||
|
|
||
|
pblHtInsert(mutex->lockpoints, location, location_length+1, tup);
|
||
|
|
||
|
}
|
||
|
|
||
|
acquired_lock(&(mutex->tup), blockCount);
|
||
|
acquired_lock(tup, blockCount);
|
||
|
|
||
|
return ret;
|
||
|
|
||
|
}
|
||
|
int __lladd_pthread_mutex_unlock(lladd_pthread_mutex_t *mutex) {
|
||
|
|
||
|
profile_tuple * tup = pblHtLookup(mutex->lockpoints, mutex->last_acquired_at, strlen(mutex->last_acquired_at)+1);
|
||
|
|
||
|
released_lock(tup);
|
||
|
released_lock(&(mutex->tup));
|
||
|
|
||
|
free(mutex->last_acquired_at);
|
||
|
|
||
|
return pthread_mutex_unlock(&(mutex->mutex));
|
||
|
|
||
|
}
|
||
|
int __lladd_pthread_mutex_destroy(lladd_pthread_mutex_t *mutex) {
|
||
|
|
||
|
/* Dump profiling info to stdout */
|
||
|
|
||
|
profile_tuple * tup;
|
||
|
|
||
|
printf("Free mutex %s Init: %s %d\n ", mutex->name, mutex->file, mutex->line);
|
||
|
print_profile_tuple(&(mutex->tup));
|
||
|
printf("\n Lock points: [mean, stddev, max] \n");
|
||
|
|
||
|
/* Now, iterate over all of the lockpoints: */
|
||
|
|
||
|
for(tup = pblHtFirst(mutex->lockpoints); tup; tup = pblHtNext(mutex->lockpoints)) {
|
||
|
printf("\t%s ", (char*)pblHtCurrentKey(mutex->lockpoints));
|
||
|
print_profile_tuple(tup);
|
||
|
printf("\n");
|
||
|
free(tup);
|
||
|
}
|
||
|
|
||
|
pblHtDelete(mutex->lockpoints);
|
||
|
|
||
|
|
||
|
return pthread_mutex_destroy(&(mutex->mutex));
|
||
|
|
||
|
}
|
||
|
|
||
|
#undef rwl
|
||
|
#undef initlock
|
||
|
#undef readlock
|
||
|
#undef writelock
|
||
|
#undef readunlock
|
||
|
#undef writeunlock
|
||
|
#undef deletelock
|
||
|
|
||
|
__profile_rwl *__profile_rw_initlock (char * file, int line) {
|
||
|
__profile_rwl * ret = malloc(sizeof(__profile_rwl));
|
||
|
|
||
|
ret->file = file;
|
||
|
ret->line = line;
|
||
|
|
||
|
init_tuple(&(ret->tup));
|
||
|
|
||
|
ret->lockpoints = pblHtCreate();
|
||
|
|
||
|
ret->lock = initlock();
|
||
|
|
||
|
return ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*static pthread_mutex_t __profile_rwl_mutex = PTHREAD_MUTEX_INITIALIZER;*/
|
||
|
|
||
|
/**
|
||
|
@todo For now, we only profile write locks...
|
||
|
*/
|
||
|
void __profile_readlock (__profile_rwl *lock, int d, char * file, int line) {
|
||
|
readlock(lock->lock, d);
|
||
|
|
||
|
}
|
||
|
void __profile_writelock (__profile_rwl *lock, int d, char * file, int line) {
|
||
|
|
||
|
char * location;
|
||
|
int location_length = asprintf(&location, "write %s %d", file, line);
|
||
|
|
||
|
profile_tuple * tup;
|
||
|
|
||
|
/** @todo Should we spin instead of using the more efficient rwl
|
||
|
implementation, or should we see how many times we were woken
|
||
|
before obtaining the lock? */
|
||
|
|
||
|
writelock(lock->lock, d);
|
||
|
|
||
|
/* pthread_mutex_lock(__profile_rwl_mutex); */
|
||
|
|
||
|
tup = pblHtLookup(lock->lockpoints, location, location_length+1);
|
||
|
|
||
|
lock->last_acquired_at = location;
|
||
|
|
||
|
if(!tup) {
|
||
|
tup = malloc(sizeof(profile_tuple));
|
||
|
|
||
|
init_tuple(tup);
|
||
|
|
||
|
pblHtInsert(lock->lockpoints, location, location_length+1, tup);
|
||
|
|
||
|
}
|
||
|
|
||
|
acquired_lock(&(lock->tup), -1);
|
||
|
acquired_lock(tup, -1);
|
||
|
|
||
|
/* pthread_mutex_unlock(__profile_rwl_mutex);*/
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
void __profile_readunlock (__profile_rwl *lock) {
|
||
|
|
||
|
readunlock(lock->lock);
|
||
|
|
||
|
|
||
|
}
|
||
|
void __profile_writeunlock (__profile_rwl *lock) {
|
||
|
|
||
|
profile_tuple * tup = pblHtLookup(lock->lockpoints, lock->last_acquired_at, strlen(lock->last_acquired_at)+1);
|
||
|
|
||
|
released_lock(tup);
|
||
|
released_lock(&(lock->tup));
|
||
|
|
||
|
free(lock->last_acquired_at);
|
||
|
|
||
|
writeunlock(lock->lock);
|
||
|
|
||
|
}
|
||
|
void __profile_deletelock (__profile_rwl *lock) {
|
||
|
|
||
|
profile_tuple * tup;
|
||
|
|
||
|
printf("Free rwl init: %s %d\n ", lock->file, lock->line);
|
||
|
print_profile_tuple(&(lock->tup));
|
||
|
printf("\n Lock points: [mean, stddev, max] \n");
|
||
|
|
||
|
for(tup = pblHtFirst(lock->lockpoints); tup; tup = pblHtNext(lock->lockpoints)) {
|
||
|
printf("\t%s ", (char*)pblHtCurrentKey(lock->lockpoints));
|
||
|
print_profile_tuple(tup);
|
||
|
printf("\n");
|
||
|
free(tup);
|
||
|
}
|
||
|
|
||
|
pblHtDelete(lock->lockpoints);
|
||
|
|
||
|
deletelock(lock->lock);
|
||
|
}
|
||
|
|