On Mon, 2007-06-11 at 13:06 +0800, Ian Kent wrote:
> On Thu, 2007-06-07 at 15:49 +0200, Anders Blomdell wrote:
> > As per request from discussions in
> > https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=241780
> > a patch against git.
>
> Yes, on closer inspection this version does look ok.
> Let me think about it for a little while in case I missed something.
>
Hi Anders,
This does indeed give some simplification to the alarm_handler function
and, as far as I can tell, retains the semantics of the original
function.
I've changed the patch around a little.
I removed the change to the mutex macros, in line with my comments
before, and I've re-structured the code a little.
Could you have a look and check that I haven't made any stupid mistakes
and that the patch still works the way you intended please.
Ian
---
diff --git a/lib/alarm.c b/lib/alarm.c
index 4a72605..c6c4ba3 100755
--- a/lib/alarm.c
+++ b/lib/alarm.c
@@ -169,6 +169,7 @@ static void *alarm_handler(void *arg)
{
struct list_head *head;
struct timespec expire;
+ struct alarm *first;
time_t now;
int status;
@@ -177,78 +178,56 @@ static void *alarm_handler(void *arg)
head = &alarms;
while (1) {
- struct alarm *current;
- /*
- * If the alarm list is empty, wait until an alarm is
- * added.
- */
- while (list_empty(head)) {
+ if (list_empty(head)) {
+ /* No alarms, wait for one to be added */
status = pthread_cond_wait(&cond, &mutex);
if (status)
fatal(status);
+ continue;
}
- current = list_entry(head->next, struct alarm, list);
+ first = list_entry(head->next, struct alarm, list);
now = time(NULL);
- if (current->time <= now) {
- struct autofs_point *ap;
-
- list_del(¤t->list);
-
- if (current->cancel) {
- free(current);
- continue;
- }
-
- ap = current->ap;
- free(current);
- alarm_unlock();
-
- state_mutex_lock(ap);
- nextstate(ap->state_pipe[1], ST_EXPIRE);
- state_mutex_unlock(ap);
-
- alarm_lock();
- continue;
- }
-
- expire.tv_sec = current->time;
- expire.tv_nsec = 0;
-
- while (1) {
- struct autofs_point *ap;
- struct alarm *next;
+ if (first->time > now) {
+ /*
+ * Wait for alarm to trigger or a new alarm
+ * to be added.
+ */
+ expire.tv_sec = first->time;
+ expire.tv_nsec = 0;
status = pthread_cond_timedwait(&cond, &mutex, &expire);
if (status && status != ETIMEDOUT)
fatal(status);
-
- next = list_entry(head->next, struct alarm, list);
- if (next->cancel) {
- list_del(&next->list);
- free(next);
- break;
+ } else {
+ /* First alarm has triggered, run it */
+
+ list_del(&first->list);
+
+ if (!first->cancel) {
+ struct autofs_point *ap = first->ap;
+ /*
+ * We need to unlock the alarm list in case
+ * some other thread holds the state_mutex
+ *_lock(ap), and is currently trying to do
+ * some alarm_* function (i.e if we don't
+ * unlock, we might deadlock).
+ */
+ alarm_unlock();
+
+ state_mutex_lock(ap);
+ nextstate(ap->state_pipe[1], ST_EXPIRE);
+ state_mutex_unlock(ap);
+
+ alarm_lock();
}
-
- if (next != current)
- break;
-
- list_del(¤t->list);
- ap = current->ap;
- free(current);
- alarm_unlock();
-
- state_mutex_lock(ap);
- nextstate(ap->state_pipe[1], ST_EXPIRE);
- state_mutex_unlock(ap);
-
- alarm_lock();
- break;
+ free(first);
}
}
+ /* Will never come here, so alarm_unlock is not necessary */
}
int alarm_start_handler(void)
_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs