diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 54fdb55..56fea99 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -182,7 +182,7 @@ static const char* info_getname(int selected_item, void *data,
 
         case INFO_BUFFER: /* buffer */
         {
-            long kib = (audiobufend - audiobuf) / 1024; /* to KiB */
+            long kib = buffer_size() / 1024; /* to KiB */
             output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true);
             snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1);
         }
@@ -272,7 +272,7 @@ static int info_speak_item(int selected_item, void * data)
         case INFO_BUFFER: /* buffer */
         {
             talk_id(LANG_BUFFER_STAT, false);
-            long kib = (audiobufend - audiobuf) / 1024; /* to KiB */
+            long kib = buffer_size() / 1024; /* to KiB */
             output_dyn_value(NULL, 0, kib, kbyte_units, true);
             break;
         }
diff --git a/apps/mp3data.c b/apps/mp3data.c
index 8a5f993..21656e2 100644
--- a/apps/mp3data.c
+++ b/apps/mp3data.c
@@ -40,6 +40,8 @@
 #include "file.h"
 #include "buffer.h"
 
+extern unsigned char *audiobuf; /* FIXME */
+
 // #define DEBUG_VERBOSE
 
 #define SYNC_MASK (0x7ffL << 21)
diff --git a/apps/playback.c b/apps/playback.c
index f3c5db3..fdbaba1 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -54,6 +54,8 @@
 #include "pcm_record.h"
 #endif
 
+extern unsigned char *audiobuf; /* FIXME */
+
 #define PLAYBACK_VOICE
 
 /* amount of guess-space to allow for codecs that must hunt and peck
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 39ed99f..80d4fce 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -102,7 +102,7 @@ static char curpath[TAG_MAXLEN+32];
 /* Used when removing duplicates. */
 static char *tempbuf;     /* Allocated when needed. */
 static long tempbufidx;   /* Current location in buffer. */
-static long tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */
+static size_t tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */
 static long tempbuf_left; /* Buffer space left. */
 static long tempbuf_pos;
 
@@ -3046,9 +3046,7 @@ static void allocate_tempbuf(void)
     tempbuf_size = 32*1024*1024;
     tempbuf = malloc(tempbuf_size);
 #else
-    tempbuf = (char *)(((long)audiobuf & ~0x03) + 0x04);
-    tempbuf_size = (long)audiobufend - (long)audiobuf - 4;
-    audiobuf += tempbuf_size;
+    tempbuf = buffer_claim(&tempbuf_size);
 #endif
 }
 
@@ -3060,7 +3058,7 @@ static void free_tempbuf(void)
 #ifdef __PCTOOL__
     free(tempbuf);
 #else
-    audiobuf -= tempbuf_size;
+    buffer_unclaim();
 #endif
     tempbuf = NULL;
     tempbuf_size = 0;
diff --git a/apps/talk.c b/apps/talk.c
index 7dbfb2e..521f296 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -44,6 +44,9 @@
 #include "debug.h"
 
 
+extern unsigned char *audiobuf; /* FIXME */
+
+
 /* Memory layout varies between targets because the
    Archos (MASCODEC) devices cannot mix voice and audio playback
  
@@ -299,7 +302,7 @@ static void load_voicefile(bool probe)
 
 #ifndef TALK_PARTIAL_LOAD
     file_size = filesize(filehandle);
-    if (file_size > audiobufend - audiobuf) /* won't fit? */
+    if (file_size > buffer_size()) /* won't fit? */
         goto load_err;
 #endif
 
@@ -311,7 +314,7 @@ static void load_voicefile(bool probe)
 #endif
 
 #ifdef TALK_PARTIAL_LOAD
-    if (load_size > audiobufend - audiobuf) /* won't fit? */
+    if (load_size > buffer_size()) /* won't fit? */
         goto load_err;
 #endif
 
@@ -351,7 +354,7 @@ static void load_voicefile(bool probe)
                 * sizeof(struct clip_entry);
 
 #ifdef TALK_PARTIAL_LOAD
-    if (load_size > audiobufend - audiobuf) /* won't fit? */
+    if (load_size > buffer_size()) /* won't fit? */
         goto load_err;
 #endif
 
@@ -591,7 +594,7 @@ static void reset_state(void)
     /* Allocate a dedicated thumbnail buffer - once */
     if (p_thumbnail == NULL)
     {
-        size_for_thumbnail = audiobufend - audiobuf;
+        size_for_thumbnail = buffer_size();
         if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE)
             size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE;
         p_thumbnail = buffer_alloc(size_for_thumbnail);
@@ -599,7 +602,7 @@ static void reset_state(void)
 #else
     /* Just use the audiobuf, without allocating anything */
     p_thumbnail = audiobuf;
-    size_for_thumbnail = audiobufend - audiobuf;
+    size_for_thumbnail = buffer_size();
 #endif
 
 #ifdef TALK_PARTIAL_LOAD
@@ -656,7 +659,7 @@ void talk_init(void)
     voicefile_size = filesize(filehandle);
 
     /* test if we can open and if it fits in the audiobuffer */
-    size_t audiobufsz = audiobufend - audiobuf;
+    size_t audiobufsz = buffer_size();
 
 #ifdef TALK_PARTIAL_LOAD
     /* we won't load the full file, we only need the index */
diff --git a/firmware/buffer.c b/firmware/buffer.c
index 4ede24d..b838060 100644
--- a/firmware/buffer.c
+++ b/firmware/buffer.c
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include "buffer.h"
 #include "panic.h"
+#include "kernel.h"
 #include "logf.h"
 
 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
@@ -31,6 +32,7 @@ unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer);
 extern unsigned char audiobuffer[];
 #endif
 
+static struct mutex audiobuf_mutex;
 unsigned char *audiobuf;
 
 #ifdef BUFFER_ALLOC_DEBUG
@@ -57,10 +59,31 @@ void buffer_init(void)
 #ifdef BUFFER_ALLOC_DEBUG
     audiobuf_orig_start = audiobuf;
 #endif /* BUFFER_ALLOC_DEBUG */
+	mutex_init(&audiobuf_mutex);
 }
 
+void *buffer_claim(size_t *size)
+{
+	if (audiobuf_mutex.locked == true)
+		panicf("Nested buffer_claim()!");
+
+	mutex_lock(&audiobuf_mutex);
+	if (size)
+		*size = audiobufend - audiobuf;
+	return audiobuf;
+}
+void buffer_unclaim(void)
+{
+	mutex_unlock(&audiobuf_mutex);
+}
+	 
+
 void *buffer_alloc(size_t size)
 {
+	/* We should make sure the the buffer is actually locked here,
+	 * better yet, we should use a magic value to make sure the 
+	 * caller here also has the buffer locked!
+	 */
     void *retval = audiobuf;
 #ifdef BUFFER_ALLOC_DEBUG
     struct buffer_start_marker *start;
@@ -127,3 +150,9 @@ void buffer_alloc_check(char *name)
     }
 }
 #endif /* BUFFER_ALLOC_DEBUG */
+
+size_t buffer_size(void)
+{
+	return audiobufend - audiobuf;
+}
+
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 509743b..e2a481e 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -672,10 +672,8 @@ static int dircache_do_rebuild(void)
     }
     else
     {
-        /* We have to long align the audiobuf to keep the buffer access fast. */
-        audiobuf += (long)((dircache_size & ~0x03) + 0x04);
-        audiobuf += DIRCACHE_RESERVE;
         allocated_size = dircache_size + DIRCACHE_RESERVE;
+        buffer_alloc(dircache_size + allocated_size);
         reserve_used = 0;
     }
     
@@ -756,16 +754,20 @@ int dircache_build(int last_size)
         return 3;
     }
 
-    dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04);
+	size_t audiobuf_size;
+	dircache_root = (struct dircache_entry *)buffer_claim(&audiobuf_size);
 
     /* Start a non-transparent rebuild. */
-    return dircache_do_rebuild();
+    int retval = dircache_do_rebuild();
+    buffer_unclaim();
+    
+    return retval;
 }
 
 /**
  * Steal the allocated dircache buffer and disable dircache.
  */
-void* dircache_steal_buffer(long *size)
+void* dircache_steal_buffer(size_t *size)
 {
     dircache_disable();
     if (dircache_size == 0)
@@ -792,10 +794,12 @@ void dircache_init(void)
     dircache_initializing = false;
     
     memset(opendirs, 0, sizeof(opendirs));
+    buffer_claim(NULL);
     for (i = 0; i < MAX_OPEN_DIRS; i++)
     {
         opendirs[i].theent.d_name = buffer_alloc(MAX_PATH);
     }
+    buffer_unclaim();
     
     queue_init(&dircache_queue, true);
     thread_id = create_thread(dircache_thread, dircache_stack,
diff --git a/firmware/export/buffer.h b/firmware/export/buffer.h
index 18f53f0..dfa6da7 100644
--- a/firmware/export/buffer.h
+++ b/firmware/export/buffer.h
@@ -34,7 +34,9 @@ extern unsigned char audiobufend[];
 extern unsigned char *audiobufend;
 #endif
 
-extern unsigned char *audiobuf;
+
+void *buffer_claim(size_t *size);
+void buffer_unclaim(void);
 
 void buffer_init(void) INIT_ATTR;
 void *buffer_alloc(size_t size);
@@ -43,4 +45,7 @@ void *buffer_alloc(size_t size);
 void buffer_alloc_check(char *name);
 #endif
 
+size_t buffer_size(void);
+
+
 #endif
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 87aaa00..be8ec08 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -90,7 +90,7 @@ void dircache_init(void) INIT_ATTR;
 int dircache_load(void);
 int dircache_save(void);
 int dircache_build(int last_size);
-void* dircache_steal_buffer(long *size);
+void* dircache_steal_buffer(size_t *size);
 bool dircache_is_enabled(void);
 bool dircache_is_initializing(void);
 void dircache_set_appflag(long mask);
