author | Alberto Bertogli
<albertito@gmail.com> 2007-04-01 04:47:08 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2008-06-24 06:10:04 UTC |
parent | 4d3dba5bd6b624572d880ffa54fea565e1e046f2 |
nmdb/dbloop.c | +4 | -0 |
nmdb/queue.c | +7 | -0 |
nmdb/queue.h | +14 | -7 |
nmdb/sparse.h | +21 | -0 |
diff --git a/nmdb/dbloop.c b/nmdb/dbloop.c index 0a7e4a7..bb20504 100644 --- a/nmdb/dbloop.c +++ b/nmdb/dbloop.c @@ -14,6 +14,7 @@ #include "req.h" #include "log.h" #include "netutils.h" +#include "sparse.h" static void *db_loop(void *arg); @@ -74,6 +75,9 @@ static void *db_loop(void *arg) if (rv != 0 && rv != ETIMEDOUT) { errlog("Error in queue_timedwait()"); + /* When the timedwait fails the lock is released, so + * we need to properly annotate this case. */ + __release(op_queue->lock); continue; } diff --git a/nmdb/queue.c b/nmdb/queue.c index eb56b09..0629f82 100644 --- a/nmdb/queue.c +++ b/nmdb/queue.c @@ -32,11 +32,18 @@ void queue_free(struct queue *q) { struct queue_entry *e; + /* We know when we're called there is no other possible queue user; + * however, we don't have any sane way to tell sparse about this, so + * fake the acquisition of the lock to comply with the operations + * performed inside. Obviously, it would be completely safe to do the + * queue_lock()/unlock(), but it'd be misleading to the reader */ + __acquire(q->lock); e = queue_get(q); while (e != NULL) { queue_entry_free(e); e = queue_get(q); } + __release(q->lock); pthread_mutex_destroy(&(q->lock)); diff --git a/nmdb/queue.h b/nmdb/queue.h index f50abe5..17a4ec0 100644 --- a/nmdb/queue.h +++ b/nmdb/queue.h @@ -5,6 +5,7 @@ #include <pthread.h> /* for mutexes */ #include <stdint.h> /* for uint32_t */ #include "req.h" /* for req_info */ +#include "sparse.h" struct queue { pthread_mutex_t lock; @@ -38,14 +39,20 @@ void queue_free(struct queue *q); struct queue_entry *queue_entry_create(); void queue_entry_free(struct queue_entry *e); -void queue_lock(struct queue *q); -void queue_unlock(struct queue *q); +void queue_lock(struct queue *q) + __acquires(q->lock); +void queue_unlock(struct queue *q) + __releases(q->lock); void queue_signal(struct queue *q); -int queue_timedwait(struct queue *q, struct timespec *ts); - -void queue_put(struct queue *q, struct queue_entry *e); -struct queue_entry *queue_get(struct queue *q); -int queue_isempty(struct queue *q); +int queue_timedwait(struct queue *q, struct timespec *ts) + __with_lock_acquired(q->lock); + +void queue_put(struct queue *q, struct queue_entry *e) + __with_lock_acquired(q->lock); +struct queue_entry *queue_get(struct queue *q) + __with_lock_acquired(q->lock); +int queue_isempty(struct queue *q) + __with_lock_acquired(q->lock); #endif diff --git a/nmdb/sparse.h b/nmdb/sparse.h new file mode 100644 index 0000000..20adafc --- /dev/null +++ b/nmdb/sparse.h @@ -0,0 +1,21 @@ + +/* Useful defines to use with sparse */ + +#ifndef _SPARSE_H +#define _SPARSE_H + +#ifdef __CHECKER__ +# define __acquires(x) __attribute__((exact_context(x,0,1))) +# define __releases(x) __attribute__((exact_context(x,1,0))) +# define __with_lock_acquired(x) __attribute__((exact_context(x,1,1))) +# define __acquire(x) __context__(x,1,0) +# define __release(x) __context__(x,-1,1) +#else +# define __acquires(x) +# define __releases(x) +# define __with_lock_acquired(x) +# define __acquire(x) (void)0 +# define __release(x) (void)0 +#endif + +#endif