Changeset 4590

Show
Ignore:
Timestamp:
11/05/08 16:51:57 (2 months ago)
Author:
martin
Message:

wrapped rwlock with profiling support

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/libstrongswan/utils/mutex.c

    r4587 r4590  
    2020#include <library.h> 
    2121#include <debug.h> 
    22 #include <utils/backtrace.h> 
    2322 
    2423#include <pthread.h> 
     
    2827#include <errno.h> 
    2928 
    30 /** 
    31  * Do not report mutexes with an overall waiting time smaller than this (in us) 
    32  */ 
    33 #define PROFILE_TRESHHOLD 1000 
    34  
    3529typedef struct private_mutex_t private_mutex_t; 
    3630typedef struct private_r_mutex_t private_r_mutex_t; 
    3731typedef struct private_condvar_t private_condvar_t; 
     32typedef struct private_rwlock_t private_rwlock_t; 
     33 
     34#ifdef LOCK_PROFILER 
     35 
     36/** 
     37 * Do not report mutexes with an overall waiting time smaller than this (in us) 
     38 */ 
     39#define PROFILE_TRESHHOLD 1000 
     40 
     41#include <utils/backtrace.h> 
     42 
     43typedef struct lock_profile_t lock_profile_t; 
     44 
     45struct lock_profile_t { 
     46 
     47    /** 
     48     * how long threads have waited for the lock in this mutex so far 
     49     */ 
     50    struct timeval waited; 
     51     
     52    /** 
     53     * backtrace where mutex has been created 
     54     */ 
     55    backtrace_t *backtrace; 
     56}; 
     57 
     58/** 
     59 * Print and cleanup mutex profiler 
     60 */ 
     61static void profiler_cleanup(lock_profile_t *profile) 
     62{ 
     63    if (profile->waited.tv_sec > 0 || 
     64        profile->waited.tv_usec > PROFILE_TRESHHOLD) 
     65    { 
     66        fprintf(stderr, "%d.%06ds in lock created at:", 
     67                profile->waited.tv_sec, profile->waited.tv_usec); 
     68        profile->backtrace->log(profile->backtrace, stderr); 
     69    } 
     70    profile->backtrace->destroy(profile->backtrace); 
     71} 
     72 
     73/** 
     74 * Initialize mutex profiler 
     75 */ 
     76static void profiler_init(lock_profile_t *profile) 
     77{ 
     78    profile->backtrace = backtrace_create(3); 
     79    timerclear(&profile->waited); 
     80} 
     81 
     82#define profiler_start(profile) { \ 
     83    struct timeval _start, _end, _diff; \ 
     84    gettimeofday(&_start, NULL); 
     85     
     86#define profiler_end(profile) \ 
     87    gettimeofday(&_end, NULL); \ 
     88    timersub(&_end, &_start, &_diff); \ 
     89    timeradd(&(profile)->waited, &_diff, &(profile)->waited); } 
     90 
     91#else /* !LOCK_PROFILER */ 
     92 
     93#define lock_profile_t struct {} 
     94#define profiler_cleanup(...) {} 
     95#define profiler_init(...) {} 
     96#define profiler_start(...) {} 
     97#define profiler_end(...) {} 
     98 
     99#endif /* LOCK_PROFILER */ 
    38100 
    39101/** 
     
    52114    pthread_mutex_t mutex; 
    53115     
    54 #ifdef LOCK_PROFILER 
    55     /** 
    56      * how long threads have waited for the lock in this mutex so far 
    57      */ 
    58     struct timeval waited; 
    59      
    60     /** 
    61      * backtrace where mutex has been created 
    62      */ 
    63     backtrace_t *backtrace; 
    64 #endif /* LOCK_PROFILER */ 
    65      
    66116    /** 
    67117     * is this a recursiv emutex, implementing private_r_mutex_t? 
    68118     */ 
    69119    bool recursive; 
     120     
     121    /** 
     122     * profiling info, if enabled 
     123     */ 
     124    lock_profile_t profile; 
    70125}; 
    71126 
     
    107162}; 
    108163 
    109 #ifdef LOCK_PROFILER 
    110 /** 
    111  * Print and cleanup mutex profiler 
    112  */ 
    113 static void profiler_cleanup(private_mutex_t *this) 
    114 
    115     if (this->waited.tv_sec > 0 || 
    116         this->waited.tv_usec > PROFILE_TRESHHOLD) 
    117     { 
    118         fprintf(stderr, "waited %d.%06ds in mutex, created at:", 
    119                 this->waited.tv_sec, this->waited.tv_usec); 
    120         this->backtrace->log(this->backtrace, stderr); 
    121     } 
    122     this->backtrace->destroy(this->backtrace); 
    123 
    124  
    125 /** 
    126  * Initialize mutex profiler 
    127  */ 
    128 static void profiler_init(private_mutex_t *this) 
    129 
    130     this->backtrace = backtrace_create(3); 
    131     timerclear(&this->waited); 
    132 
     164/** 
     165 * private data of rwlock 
     166 */ 
     167struct private_rwlock_t { 
     168 
     169    /** 
     170     * public functions 
     171     */ 
     172    rwlock_t public; 
     173     
     174    /** 
     175     * wrapped pthread rwlock 
     176     */ 
     177    pthread_rwlock_t rwlock; 
     178     
     179    /** 
     180     * profiling info, if enabled 
     181     */ 
     182    lock_profile_t profile; 
     183}; 
    133184 
    134185/** 
     
    137188static void lock(private_mutex_t *this) 
    138189{ 
    139     struct timeval start, end, diff; 
    140  
    141     gettimeofday(&start, NULL); 
     190    profiler_start(&this->profile); 
    142191    if (pthread_mutex_lock(&this->mutex)) 
    143192    { 
    144193        DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); 
    145194    } 
    146     gettimeofday(&end, NULL); 
    147      
    148     timersub(&end, &start, &diff); 
    149     timeradd(&this->waited, &diff, &this->waited); 
    150 
    151 #else /* !LOCK_PROFILER */ 
    152  
    153 /** dummy implementations */ 
    154 static void profiler_cleanup(private_mutex_t *this) {} 
    155 static void profiler_init(private_mutex_t *this) {} 
    156  
    157 /** 
    158  * Implementation of mutex_t.lock. 
    159  */ 
    160 static void lock(private_mutex_t *this) 
    161 
    162     if (pthread_mutex_lock(&this->mutex)) 
    163     { 
    164         DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); 
    165     } 
    166 
    167 #endif /* LOCK_PROFILER */ 
     195    profiler_end(&this->profile); 
     196
    168197 
    169198/** 
     
    225254static void mutex_destroy(private_mutex_t *this) 
    226255{ 
    227     profiler_cleanup(this); 
     256    profiler_cleanup(&this->profile); 
    228257    pthread_mutex_destroy(&this->mutex); 
    229258    free(this); 
     
    235264static void mutex_destroy_r(private_r_mutex_t *this) 
    236265{ 
    237     profiler_cleanup(&this->generic); 
     266    profiler_cleanup(&this->generic.profile); 
    238267    pthread_mutex_destroy(&this->generic.mutex); 
    239268    pthread_key_delete(this->times); 
     
    259288            pthread_key_create(&this->times, NULL); 
    260289            this->generic.recursive = TRUE; 
    261             profiler_init(&this->generic); 
     290            profiler_init(&this->generic.profile); 
    262291            this->thread = 0; 
    263292             
     
    275304            pthread_mutex_init(&this->mutex, NULL); 
    276305            this->recursive = FALSE; 
    277             profiler_init(this); 
     306            profiler_init(&this->profile); 
    278307             
    279308            return &this->public; 
     
    392421} 
    393422 
     423/** 
     424 * Implementation of rwlock_t.read_lock 
     425 */ 
     426static void read_lock(private_rwlock_t *this) 
     427{ 
     428    profiler_start(&this->profile); 
     429    pthread_rwlock_rdlock(&this->rwlock); 
     430    profiler_end(&this->profile); 
     431} 
     432 
     433/** 
     434 * Implementation of rwlock_t.write_lock 
     435 */ 
     436static void write_lock(private_rwlock_t *this) 
     437{ 
     438    profiler_start(&this->profile); 
     439    pthread_rwlock_wrlock(&this->rwlock); 
     440    profiler_end(&this->profile); 
     441} 
     442 
     443/** 
     444 * Implementation of rwlock_t.unlock 
     445 */ 
     446static void rw_unlock(private_rwlock_t *this) 
     447{ 
     448    pthread_rwlock_unlock(&this->rwlock); 
     449} 
     450 
     451/** 
     452 * Implementation of rwlock_t.destroy 
     453 */ 
     454static void rw_destroy(private_rwlock_t *this) 
     455{ 
     456    pthread_rwlock_destroy(&this->rwlock); 
     457    profiler_cleanup(&this->profile); 
     458    free(this); 
     459} 
     460 
     461/* 
     462 * see header file 
     463 */ 
     464rwlock_t *rwlock_create(rwlock_type_t type) 
     465{ 
     466    switch (type) 
     467    { 
     468        case RWLOCK_DEFAULT: 
     469        default: 
     470        { 
     471            private_rwlock_t *this = malloc_thing(private_rwlock_t); 
     472             
     473            this->public.read_lock = (void(*)(rwlock_t*))read_lock; 
     474            this->public.write_lock = (void(*)(rwlock_t*))write_lock; 
     475            this->public.unlock = (void(*)(rwlock_t*))rw_unlock; 
     476            this->public.destroy = (void(*)(rwlock_t*))rw_destroy; 
     477             
     478            pthread_rwlock_init(&this->rwlock, NULL); 
     479            profiler_init(&this->profile); 
     480             
     481            return &this->public; 
     482        } 
     483    } 
     484} 
     485 
  • trunk/src/libstrongswan/utils/mutex.h

    r3589 r4590  
    2424typedef struct mutex_t mutex_t; 
    2525typedef struct condvar_t condvar_t; 
     26typedef struct rwlock_t rwlock_t; 
    2627typedef enum mutex_type_t mutex_type_t; 
    2728typedef enum condvar_type_t condvar_type_t; 
     29typedef enum rwlock_type_t rwlock_type_t; 
    2830 
    2931#include <library.h> 
     
    4547    /** default condvar */ 
    4648    CONDVAR_DEFAULT = 0, 
     49}; 
     50 
     51/** 
     52 * Type of read-write lock. 
     53 */ 
     54enum rwlock_type_t { 
     55    /** default condvar */ 
     56    RWLOCK_DEFAULT  = 0, 
    4757}; 
    4858 
     
    106116 
    107117/** 
     118 * Read-Write lock wrapper. 
     119 */ 
     120struct rwlock_t { 
     121 
     122    /** 
     123     * Acquire the read lock. 
     124     */ 
     125    void (*read_lock)(rwlock_t *this); 
     126     
     127    /** 
     128     * Acquire the write lock. 
     129     */ 
     130    void (*write_lock)(rwlock_t *this); 
     131     
     132    /** 
     133     * Release any acquired lock. 
     134     */ 
     135    void (*unlock)(rwlock_t *this); 
     136     
     137    /** 
     138     * Destroy the read-write lock. 
     139     */ 
     140    void (*destroy)(rwlock_t *this); 
     141}; 
     142 
     143/** 
    108144 * Create a mutex instance. 
    109145 * 
     
    121157condvar_t *condvar_create(condvar_type_t type); 
    122158 
     159/** 
     160 * Create a read-write lock instance. 
     161 * 
     162 * @param type      type of rwlock to create 
     163 * @return          unlocked rwlock instance 
     164 */ 
     165rwlock_t *rwlock_create(rwlock_type_t type); 
     166 
    123167#endif /* MUTEX_H_ @}*/