quake: properly synchronize zone.c

Preventative measures. Somehow SDLQuake managed without these...

Change-Id: Icef15f3f653fa115ad8fb1ccc3f9682e453701c3
diff --git a/apps/plugins/sdl/progs/quake/zone.c b/apps/plugins/sdl/progs/quake/zone.c
index e30d7f8..4b63ada 100644
--- a/apps/plugins/sdl/progs/quake/zone.c
+++ b/apps/plugins/sdl/progs/quake/zone.c
@@ -45,6 +45,8 @@
 void Cache_FreeLow (int new_low_hunk);
 void Cache_FreeHigh (int new_high_hunk);
 
+// prevent race conditions
+static struct mutex zone_mutex;
 
 /*
 ==============================================================================
@@ -73,6 +75,7 @@
 */
 void Z_ClearZone (memzone_t *zone, int size)
 {
+        rb->mutex_lock(&zone_mutex);
 	memblock_t	*block;
 	
 // set the entire zone to one free block
@@ -88,6 +91,7 @@
 	block->tag = 0;			// free block
 	block->id = ZONEID;
 	block->size = size - sizeof(memzone_t);
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -98,6 +102,7 @@
 */
 void Z_Free (void *ptr)
 {
+        rb->mutex_lock(&zone_mutex);
 	memblock_t	*block, *other;
 	
 	if (!ptr)
@@ -131,6 +136,7 @@
 		if (other == mainzone->rover)
 			mainzone->rover = block;
 	}
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -154,6 +160,7 @@
 
 void *Z_TagMalloc (int size, int tag)
 {
+        rb->mutex_lock(&zone_mutex);
 	int		extra;
 	memblock_t	*start, *rover, *new, *base;
 
@@ -174,7 +181,10 @@
 	do
 	{
 		if (rover == start)	// scaned all the way around the list
+                {
+                    rb->mutex_unlock(&zone_mutex);
 			return NULL;
+                }
 		if (rover->tag)
 			base = rover = rover->next;
 		else
@@ -207,6 +217,7 @@
 // marker for memory trash testing
 	*(int *)((byte *)base + base->size - 4) = ZONEID;
 
+        rb->mutex_unlock(&zone_mutex);
 	return (void *) ((byte *)base + sizeof(memblock_t));
 }
 
@@ -218,6 +229,7 @@
 */
 void Z_Print (memzone_t *zone)
 {
+        rb->mutex_lock(&zone_mutex);
 	memblock_t	*block;
 	
 	Con_Printf ("zone size: %i  location: %p\n",mainzone->size,mainzone);
@@ -236,6 +248,7 @@
 		if (!block->tag && !block->next->tag)
 			Con_Printf ("ERROR: two consecutive free blocks\n");
 	}
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -246,6 +259,7 @@
 */
 void Z_CheckHeap (void)
 {
+        rb->mutex_lock(&zone_mutex);
 	memblock_t	*block;
 	
 	for (block = mainzone->blocklist.next ; ; block = block->next)
@@ -259,6 +273,7 @@
 		if (!block->tag && !block->next->tag)
 			Sys_Error ("Z_CheckHeap: two consecutive free blocks\n");
 	}
+        rb->mutex_unlock(&zone_mutex);
 }
 
 //============================================================================
@@ -292,6 +307,7 @@
 */
 void Hunk_Check (void)
 {
+        rb->mutex_lock(&zone_mutex);
 	hunk_t	*h;
 	
 	for (h = (hunk_t *)hunk_base ; (byte *)h != hunk_base + hunk_low_used ; )
@@ -302,6 +318,7 @@
 			Sys_Error ("Hunk_Check: bad size");
 		h = (hunk_t *)((byte *)h+h->size);
 	}
+        rb->mutex_unlock(&zone_mutex);
 }
 
 /*
@@ -314,6 +331,7 @@
 */
 void Hunk_Print (qboolean all)
 {
+        rb->mutex_lock(&zone_mutex);
 	hunk_t	*h, *next, *endlow, *starthigh, *endhigh;
 	int		count, sum;
 	int		totalblocks;
@@ -388,7 +406,7 @@
 
 	Con_Printf ("-------------------------\n");
 	Con_Printf ("%8i total blocks\n", totalblocks);
-	
+        rb->mutex_unlock(&zone_mutex);
 }
 
 /*
@@ -398,6 +416,7 @@
 */
 void *Hunk_AllocName (int size, char *name)
 {
+        rb->mutex_lock(&zone_mutex);
 	hunk_t	*h;
 	
 #ifdef PARANOID
@@ -423,6 +442,7 @@
 	h->sentinal = HUNK_SENTINAL;
 	Q_strncpy (h->name, name, 8);
 	
+        rb->mutex_unlock(&zone_mutex);
 	return (void *)(h+1);
 }
 
@@ -438,30 +458,39 @@
 
 int	Hunk_LowMark (void)
 {
-	return hunk_low_used;
+        rb->mutex_lock(&zone_mutex);
+	int x = hunk_low_used;
+        rb->mutex_unlock(&zone_mutex);
+        return x;
 }
 
 void Hunk_FreeToLowMark (int mark)
 {
+        rb->mutex_lock(&zone_mutex);
 	if (mark < 0 || mark > hunk_low_used)
 		Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark);
 	memset (hunk_base + mark, 0, hunk_low_used - mark);
 	hunk_low_used = mark;
+        rb->mutex_unlock(&zone_mutex);
 }
 
 int	Hunk_HighMark (void)
 {
+        rb->mutex_lock(&zone_mutex);
 	if (hunk_tempactive)
 	{
 		hunk_tempactive = false;
 		Hunk_FreeToHighMark (hunk_tempmark);
 	}
 
-	return hunk_high_used;
+	int x = hunk_high_used;
+        rb->mutex_unlock(&zone_mutex);
+        return x;
 }
 
 void Hunk_FreeToHighMark (int mark)
 {
+        rb->mutex_lock(&zone_mutex);
 	if (hunk_tempactive)
 	{
 		hunk_tempactive = false;
@@ -471,6 +500,7 @@
 		Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark);
 	memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark);
 	hunk_high_used = mark;
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -481,6 +511,7 @@
 */
 void *Hunk_HighAllocName (int size, char *name)
 {
+        rb->mutex_lock(&zone_mutex);
 	hunk_t	*h;
 
 	if (size < 0)
@@ -501,6 +532,7 @@
 	if (hunk_size - hunk_low_used - hunk_high_used < size)
 	{
 		Con_Printf ("Hunk_HighAlloc: failed on %i bytes\n",size);
+                rb->mutex_unlock(&zone_mutex);
 		return NULL;
 	}
 
@@ -514,6 +546,7 @@
 	h->sentinal = HUNK_SENTINAL;
 	Q_strncpy (h->name, name, 8);
 
+        rb->mutex_unlock(&zone_mutex);
 	return (void *)(h+1);
 }
 
@@ -527,6 +560,7 @@
 */
 void *Hunk_TempAlloc (int size)
 {
+        rb->mutex_lock(&zone_mutex);
 	void	*buf;
 
 	size = (size+15)&~15;
@@ -543,6 +577,7 @@
 
 	hunk_tempactive = true;
 
+        rb->mutex_unlock(&zone_mutex);
 	return buf;
 }
 
@@ -574,6 +609,7 @@
 */
 void Cache_Move ( cache_system_t *c)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t		*new;
 
 // we are clearing up space at the bottom, so only allocate it late
@@ -594,6 +630,7 @@
 
 		Cache_Free (c->user);		// tough luck...
 	}
+        rb->mutex_unlock(&zone_mutex);
 }
 
 /*
@@ -605,15 +642,22 @@
 */
 void Cache_FreeLow (int new_low_hunk)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t	*c;
 	
 	while (1)
 	{
 		c = cache_head.next;
 		if (c == &cache_head)
+                {
+                        rb->mutex_unlock(&zone_mutex);
 			return;		// nothing in cache at all
+                }
 		if ((byte *)c >= hunk_base + new_low_hunk)
+                {
+                        rb->mutex_unlock(&zone_mutex);
 			return;		// there is space to grow the hunk
+                }
 		Cache_Move ( c );	// reclaim the space
 	}
 }
@@ -627,6 +671,7 @@
 */
 void Cache_FreeHigh (int new_high_hunk)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t	*c, *prev;
 	
 	prev = NULL;
@@ -634,9 +679,15 @@
 	{
 		c = cache_head.prev;
 		if (c == &cache_head)
+                {
+                        rb->mutex_unlock(&zone_mutex);
 			return;		// nothing in cache at all
+                }
 		if ( (byte *)c + c->size <= hunk_base + hunk_size - new_high_hunk)
+                {
+                        rb->mutex_unlock(&zone_mutex);
 			return;		// there is space to grow the hunk
+                }
 		if (c == prev)
 			Cache_Free (c->user);	// didn't move out of the way
 		else
@@ -649,6 +700,7 @@
 
 void Cache_UnlinkLRU (cache_system_t *cs)
 {
+        rb->mutex_lock(&zone_mutex);
 	if (!cs->lru_next || !cs->lru_prev)
 		Sys_Error ("Cache_UnlinkLRU: NULL link");
 
@@ -656,10 +708,12 @@
 	cs->lru_prev->lru_next = cs->lru_next;
 	
 	cs->lru_prev = cs->lru_next = NULL;
+        rb->mutex_unlock(&zone_mutex);
 }
 
 void Cache_MakeLRU (cache_system_t *cs)
 {
+        rb->mutex_lock(&zone_mutex);
 	if (cs->lru_next || cs->lru_prev)
 		Sys_Error ("Cache_MakeLRU: active link");
 
@@ -667,6 +721,7 @@
 	cs->lru_next = cache_head.lru_next;
 	cs->lru_prev = &cache_head;
 	cache_head.lru_next = cs;
+        rb->mutex_unlock(&zone_mutex);
 }
 
 /*
@@ -679,6 +734,7 @@
 */
 cache_system_t *Cache_TryAlloc (int size, qboolean nobottom)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t	*cs, *new;
 	
 // is the cache completely empty?
@@ -696,6 +752,7 @@
 		new->prev = new->next = &cache_head;
 		
 		Cache_MakeLRU (new);
+                rb->mutex_unlock(&zone_mutex);
 		return new;
 	}
 	
@@ -720,6 +777,7 @@
 				
 				Cache_MakeLRU (new);
 	
+                                rb->mutex_unlock(&zone_mutex);
 				return new;
 			}
 		}
@@ -743,9 +801,11 @@
 		
 		Cache_MakeLRU (new);
 
+                rb->mutex_unlock(&zone_mutex);
 		return new;
 	}
 	
+        rb->mutex_unlock(&zone_mutex);
 	return NULL;		// couldn't allocate
 }
 
@@ -758,8 +818,10 @@
 */
 void Cache_Flush (void)
 {
+        rb->mutex_lock(&zone_mutex);
 	while (cache_head.next != &cache_head)
 		Cache_Free ( cache_head.next->user );	// reclaim the space
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -823,6 +885,7 @@
 */
 void Cache_Free (cache_user_t *c)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t	*cs;
 
 	if (!c->data)
@@ -837,6 +900,7 @@
 	c->data = NULL;
 
 	Cache_UnlinkLRU (cs);
+        rb->mutex_unlock(&zone_mutex);
 }
 
 
@@ -848,10 +912,14 @@
 */
 void *Cache_Check (cache_user_t *c)
 {
+        rb->mutex_lock(&zone_mutex);
 	cache_system_t	*cs;
 
 	if (!c->data)
+        {
+            rb->mutex_unlock(&zone_mutex);
 		return NULL;
+        }
 
 	cs = ((cache_system_t *)c->data) - 1;
 
@@ -859,6 +927,7 @@
 	Cache_UnlinkLRU (cs);
 	Cache_MakeLRU (cs);
 	
+        rb->mutex_unlock(&zone_mutex);
 	return c->data;
 }
 
@@ -870,6 +939,8 @@
 */
 void *Cache_Alloc (cache_user_t *c, int size, char *name)
 {
+        rb->mutex_lock(&zone_mutex);
+    
 	cache_system_t	*cs;
 
 	if (c->data)
@@ -899,6 +970,7 @@
 		Cache_Free ( cache_head.lru_prev->user );
 	} 
 	
+        rb->mutex_unlock(&zone_mutex);
 	return Cache_Check (c);
 }
 
@@ -912,6 +984,8 @@
 */
 void Memory_Init (void *buf, int size)
 {
+    rb->mutex_init(&zone_mutex);
+    
 	int p;
 	int zonesize = DYNAMIC_SIZE;