git » libfilo » commit a6bd4eb

Allocate waiter ranges dynamically.

author Alberto Bertogli
2005-04-23 23:15:28 UTC
committer Alberto Bertogli
2005-04-23 23:15:28 UTC
parent 2a085167f937108f2a940f32f989ef81dd4e39fe

Allocate waiter ranges dynamically.
This patch makes waiter ranges to be allocated dynamically instead of them
living in the thread's stack. See the big comment for details.

libfilo.c +29 -26

diff --git a/libfilo.c b/libfilo.c
index 361f7e0..e9c30cd 100644
--- a/libfilo.c
+++ b/libfilo.c
@@ -319,39 +319,45 @@ int filo_trylock(filock_t *fl, off_t start, off_t len, int mode)
 
 static void wait_on(filock_t *fl, off_t start, off_t end, int mode)
 {
-	/* all waiter_ranges live on the heap and are created and destroyed
-	 * here. A wr is born here, go to bed in the locking below, until
-	 * wake_up() wakes us up and he dies. While it is manipulated several
-	 * times outside this function, here is the only place where it's
-	 * actually modified. */
-	struct waiter_range wr;
+	/* all waiter_ranges are created and destroyed here. A wr is born
+	 * here, go to bed in the locking below, until wake_up() wakes us up
+	 * and he dies. While it is manipulated several times outside this
+	 * function, here is the only place where it's actually modified; it
+	 * used to be allocated directly on the stack, but maybe some stuff
+	 * assume thread stack is not touched by other threads and it could
+	 * cause some problems in the future; remember: "better safe than
+	 * sorry". */
+	struct waiter_range *wr;
+	wr = malloc(sizeof(struct waiter_range));
 
 	/* initialize wr */
-	wr.start = start;
-	wr.end = end;
-	wr.mode = mode;
-	wr.owner = pthread_self();
-	wr.next = NULL;
-	wr.prev = NULL;
+	wr->start = start;
+	wr->end = end;
+	wr->mode = mode;
+	wr->owner = pthread_self();
+	wr->next = NULL;
+	wr->prev = NULL;
 
-	sem_init(&(wr.sem), 0, 0);
+	sem_init(&(wr->sem), 0, 0);
 
 	/* add to the semi-circular list */
 	if (fl->waiters == NULL) {
-		wr.next = NULL;
-		wr.prev = ≀
-		fl->waiters = ≀
+		wr->next = NULL;
+		wr->prev = wr;
+		fl->waiters = wr;
 	} else {
-		wr.next = NULL;
-		wr.prev = fl->waiters->prev;
-		fl->waiters->prev->next = ≀
-		fl->waiters->prev = ≀
+		wr->next = NULL;
+		wr->prev = fl->waiters->prev;
+		fl->waiters->prev->next = wr;
+		fl->waiters->prev = wr;
 	}
 
 	fl_unlock(fl);
 
 	/* block until some other thread wakes us up */
-	sem_wait(&(wr.sem));
+	sem_wait(&(wr->sem));
+
+	free(wr);
 }
 
 static void wake_up(filock_t *fl, off_t start, off_t end)
@@ -383,11 +389,8 @@ static void wake_up(filock_t *fl, off_t start, off_t end)
 				wr->next->prev = wr->prev;
 			}
 
-			/* it lives on wait_on()'s stack, there's no need to
-			 * free it */
-
-			/* this will wake the thread up (and the thread will
-			 * destroy wr) */
+			/* this will wake the thread up, which is blocked in
+			 * wait_on(), and it will then free wr */
 			sem_post(&(wr->sem));
 
 			return;