diff options
author | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-04-03 16:49:30 -0700 |
---|---|---|
committer | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-04-21 14:52:42 -0700 |
commit | 7439e734379124894652de5ea514ac91cc38676e (patch) | |
tree | 9a0c876afc65acca2806ecfff56216a72588be63 | |
parent | 8b0627dc02859dce9a7649b6796054ee932a9262 (diff) |
libwimaxll-i2400m: insert cancellation handlers when taking mutexes
Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
-rw-r--r-- | lib/i2400m.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/i2400m.c b/lib/i2400m.c index a3ec11c..2abc00f 100644 --- a/lib/i2400m.c +++ b/lib/i2400m.c @@ -45,7 +45,9 @@ * * When the callback from libwimaxll comes back with the response, if * it was a reply to said message, then the waiter for that is woken - * up (using pthread mutexes and conditional variables). + * up (using pthread mutexes and conditional variables). See \ref + * cancellation for more information on what happens when the thread + * is cancelled. * * When a report is received, the report callback is called; care has * to be taken not to deadlock. See i2400m_report_cb(). @@ -102,6 +104,13 @@ * * } * @endcode + * + * \section cancellation Thread cancellation + * + * All the code that takes mutexes pushes a cleanup handler that will + * unlock the mutex if the thread is cancelled. This is designed to + * work only with deferred thread cancellation models. Check POSIX for + * more information. */ #include <wimaxll/i2400m.h> #include <pthread.h> @@ -181,6 +190,8 @@ int i2400m_msg_to_user_cb(struct wimaxll_handle *wmx, void *_i2400m, goto out; mt = wimaxll_le16_to_cpu(hdr->type); + pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, + &i2400m->mutex); pthread_mutex_lock(&i2400m->mutex); if (mt == i2400m->mt_pending) { i2400m->mt_pending = I2400M_MT_INVALID; @@ -192,6 +203,7 @@ int i2400m_msg_to_user_cb(struct wimaxll_handle *wmx, void *_i2400m, pthread_cond_signal(&i2400m->cond); } pthread_mutex_unlock(&i2400m->mutex); + pthread_cleanup_pop(0); /* this is ran outside of the lock because it doesn't need * much tracking info. */ if (mt & I2400M_MT_REPORT_MASK && i2400m->report_cb) @@ -263,10 +275,13 @@ error_calloc: */ void i2400m_destroy(struct i2400m *i2400m) { + pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, + &i2400m->mutex); pthread_mutex_lock(&i2400m->mutex); i2400m->mt_result = -EINTR; pthread_cond_broadcast(&i2400m->cond); pthread_mutex_unlock(&i2400m->mutex); + pthread_cleanup_pop(0); wimaxll_close(i2400m->wmx); free(i2400m); } @@ -345,6 +360,8 @@ int i2400m_msg_to_dev(struct i2400m *i2400m, /* No need to check msg & payload consistency, the kernel will do for us */ /* Setup the completion, ack_skb ("we are waiting") and send * the message to the device */ + pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, + &i2400m->mutex); pthread_mutex_lock(&i2400m->mutex); i2400m->mt_pending = msg_type; i2400m->mt_cb = cb; @@ -361,6 +378,7 @@ int i2400m_msg_to_dev(struct i2400m *i2400m, error_msg_write: i2400m->mt_pending = I2400M_MT_INVALID; pthread_mutex_unlock(&i2400m->mutex); + pthread_cleanup_pop(0); return result; } |