diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 061934335df471767c614a3d4266d9f4d41f301c..260a08c437d7b76777bc119ccaab311de39498a4 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/cli.h"
 #include "asterisk/stringfields.h"
+#include "asterisk/linkedlists.h"
 
 #define MAX_MOHFILES 512
 #define MAX_MOHFILE_LEN 128
@@ -139,24 +140,23 @@ struct mohclass {
 	int pid;		/* PID of mpg123 */
 	time_t start;
 	pthread_t thread;
-	struct mohdata *members;
 	/* Source of audio */
 	int srcfd;
 	/* FD for timing source */
 	int pseudofd;
-	struct mohclass *next;
+	AST_LIST_HEAD_NOLOCK(, mohdata) members;
+	AST_LIST_ENTRY(mohclass) list;
 };
 
 struct mohdata {
 	int pipe[2];
 	int origwfmt;
 	struct mohclass *parent;
-	struct mohdata *next;
+	struct ast_frame f;
+	AST_LIST_ENTRY(mohdata) list;
 };
 
-static struct mohclass *mohclasses;
-
-AST_MUTEX_DEFINE_STATIC(moh_lock);
+AST_LIST_HEAD_STATIC(mohclasses, mohclass);
 
 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
 #define MPG_123 "/usr/bin/mpg123"
@@ -165,18 +165,16 @@ AST_MUTEX_DEFINE_STATIC(moh_lock);
 
 static void ast_moh_free_class(struct mohclass **class) 
 {
-	struct mohdata *members, *mtmp;
+	struct mohdata *member;
+	
+	while ((member = AST_LIST_REMOVE_HEAD(&((*class)->members), list)))
+		free(member);
 	
-	members = (*class)->members;
-	while(members) {
-		mtmp = members;
-		members = members->next;
-		free(mtmp);
-	}
 	if ((*class)->thread) {
 		pthread_cancel((*class)->thread);
 		(*class)->thread = 0;
 	}
+
 	free(*class);
 	*class = NULL;
 }
@@ -515,7 +513,7 @@ static void *monmp3thread(void *data)
 			}
 			res = 8 * MOH_MS_INTERVAL;	/* 8 samples per millisecond */
 		}
-		if (!class->members)
+		if (AST_LIST_EMPTY(&class->members))
 			continue;
 		/* Read mp3 audio */
 		len = ast_codec_get_len(class->format, res);
@@ -538,16 +536,15 @@ static void *monmp3thread(void *data)
 			continue;
 		}
 		pthread_testcancel();
-		ast_mutex_lock(&moh_lock);
-		moh = class->members;
-		while (moh) {
+		AST_LIST_LOCK(&mohclasses);
+		AST_LIST_TRAVERSE(&class->members, moh, list) {
 			/* Write data */
-			if ((res = write(moh->pipe[1], sbuf, res2)) != res2) 
+			if ((res = write(moh->pipe[1], sbuf, res2)) != res2) {
 				if (option_debug)
 					ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
-			moh = moh->next;
+			}
 		}
-		ast_mutex_unlock(&moh_lock);
+		AST_LIST_UNLOCK(&mohclasses);
 	}
 	return NULL;
 }
@@ -607,60 +604,58 @@ static int moh4_exec(struct ast_channel *chan, void *data)
 	return 0;
 }
 
+/*! \note This function should be called with the mohclasses list locked */
 static struct mohclass *get_mohbyname(const char *name)
 {
-	struct mohclass *moh;
-	moh = mohclasses;
-	while (moh) {
+	struct mohclass *moh = NULL;
+
+	AST_LIST_TRAVERSE(&mohclasses, moh, list) {
 		if (!strcasecmp(name, moh->name))
-			return moh;
-		moh = moh->next;
+			break;
 	}
-	return NULL;
+
+	return moh;
 }
 
 static struct mohdata *mohalloc(struct mohclass *cl)
 {
 	struct mohdata *moh;
 	long flags;	
+	
 	if (!(moh = ast_calloc(1, sizeof(*moh))))
 		return NULL;
+	
 	if (pipe(moh->pipe)) {
 		ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
 		free(moh);
 		return NULL;
 	}
+
 	/* Make entirely non-blocking */
 	flags = fcntl(moh->pipe[0], F_GETFL);
 	fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
 	flags = fcntl(moh->pipe[1], F_GETFL);
 	fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
+
+	moh->f.frametype = AST_FRAME_VOICE;
+	moh->f.subclass = cl->format;
+	moh->f.offset = AST_FRIENDLY_OFFSET;
+
 	moh->parent = cl;
-	moh->next = cl->members;
-	cl->members = moh;
+	AST_LIST_INSERT_HEAD(&cl->members, moh, list);
+	
 	return moh;
 }
 
 static void moh_release(struct ast_channel *chan, void *data)
 {
-	struct mohdata *moh = data, *prev, *cur;
+	struct mohdata *moh = data;
 	int oldwfmt;
-	ast_mutex_lock(&moh_lock);
-	/* Unlink */
-	prev = NULL;
-	cur = moh->parent->members;
-	while (cur) {
-		if (cur == moh) {
-			if (prev)
-				prev->next = cur->next;
-			else
-				moh->parent->members = cur->next;
-			break;
-		}
-		prev = cur;
-		cur = cur->next;
-	}
-	ast_mutex_unlock(&moh_lock);
+
+	AST_LIST_LOCK(&mohclasses);
+	AST_LIST_REMOVE(&moh->parent->members, moh, list);	
+	AST_LIST_UNLOCK(&mohclasses);
+	
 	close(moh->pipe[0]);
 	close(moh->pipe[1]);
 	oldwfmt = moh->origwfmt;
@@ -693,7 +688,6 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
 
 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
 {
-	struct ast_frame f;
 	struct mohdata *moh = data;
 	short buf[1280 + AST_FRIENDLY_OFFSET / 2];
 	int res;
@@ -708,25 +702,14 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
 		len = sizeof(buf) - AST_FRIENDLY_OFFSET;
 	}
 	res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
-#if 0
-	if (res != len) {
-		ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
-	}
-#endif
 	if (res <= 0)
 		return 0;
 
-	memset(&f, 0, sizeof(f));
-	
-	f.frametype = AST_FRAME_VOICE;
-	f.subclass = moh->parent->format;
-	f.mallocd = 0;
-	f.datalen = res;
-	f.data = buf + AST_FRIENDLY_OFFSET / 2;
-	f.offset = AST_FRIENDLY_OFFSET;
-	f.samples = ast_codec_get_samples(&f);
-
-	if (ast_write(chan, &f) < 0) {
+	moh->f.datalen = res;
+	moh->f.data = buf + AST_FRIENDLY_OFFSET / 2;
+	moh->f.samples = ast_codec_get_samples(&moh->f);
+
+	if (ast_write(chan, &moh->f) < 0) {
 		ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
 		return -1;
 	}
@@ -804,7 +787,7 @@ static int moh_register(struct mohclass *moh, int reload)
 #ifdef HAVE_ZAPTEL
 	int x;
 #endif
-	ast_mutex_lock(&moh_lock);
+	AST_LIST_LOCK(&mohclasses);
 	if (get_mohbyname(moh->name)) {
 		if (reload) {
 			ast_log(LOG_DEBUG, "Music on Hold class '%s' left alone from initial load.\n", moh->name);
@@ -812,10 +795,10 @@ static int moh_register(struct mohclass *moh, int reload)
 			ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
 		}
 		free(moh);	
-		ast_mutex_unlock(&moh_lock);
+		AST_LIST_UNLOCK(&mohclasses);
 		return -1;
 	}
-	ast_mutex_unlock(&moh_lock);
+	AST_LIST_UNLOCK(&mohclasses);
 
 	time(&moh->start);
 	moh->start -= respawn_time;
@@ -864,10 +847,11 @@ static int moh_register(struct mohclass *moh, int reload)
 		ast_moh_free_class(&moh);
 		return -1;
 	}
-	ast_mutex_lock(&moh_lock);
-	moh->next = mohclasses;
-	mohclasses = moh;
-	ast_mutex_unlock(&moh_lock);
+
+	AST_LIST_LOCK(&mohclasses);
+	AST_LIST_INSERT_HEAD(&mohclasses, moh, list);
+	AST_LIST_UNLOCK(&mohclasses);
+	
 	return 0;
 }
 
@@ -887,9 +871,9 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *class)
 		class = chan->musicclass;
 	if (ast_strlen_zero(class))
 		class = "default";
-	ast_mutex_lock(&moh_lock);
+	AST_LIST_LOCK(&mohclasses);
 	mohclass = get_mohbyname(class);
-	ast_mutex_unlock(&moh_lock);
+	AST_LIST_UNLOCK(&mohclasses);
 
 	if (!mohclass) {
 		ast_log(LOG_WARNING, "No class: %s\n", (char *)class);
@@ -1060,16 +1044,15 @@ static int load_moh_classes(int reload)
 
 static void ast_moh_destroy(void)
 {
-	struct mohclass *moh, *tmp;
+	struct mohclass *moh;
 	char buff[8192];
-	int bytes, tbytes=0, stime = 0, pid = 0;
+	int bytes, tbytes = 0, stime = 0, pid = 0;
 
 	if (option_verbose > 1)
 		ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n");
-	ast_mutex_lock(&moh_lock);
-	moh = mohclasses;
 
-	while (moh) {
+	AST_LIST_LOCK(&mohclasses);
+	while ((moh = AST_LIST_REMOVE_HEAD(&mohclasses, list))) {
 		if (moh->pid) {
 			ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
 			stime = time(NULL) + 2;
@@ -1083,18 +1066,14 @@ static void ast_moh_destroy(void)
 			kill(pid, SIGTERM);
 			usleep(100000);
 			kill(pid, SIGKILL);
-			while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime) {
+			while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime)
 				tbytes = tbytes + bytes;
-			}
 			ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
 			close(moh->srcfd);
 		}
-		tmp = moh;
-		moh = moh->next;
-		ast_moh_free_class(&tmp);
+		ast_moh_free_class(&moh);
 	}
-	mohclasses = NULL;
-	ast_mutex_unlock(&moh_lock);
+	AST_LIST_UNLOCK(&mohclasses);
 }
 
 static void moh_on_off(int on)
@@ -1108,7 +1087,7 @@ static void moh_on_off(int on)
 			else
 				ast_deactivate_generator(chan);
 		}
-		ast_mutex_unlock(&chan->lock);
+		ast_channel_unlock(chan);
 	}
 }
 
@@ -1129,8 +1108,8 @@ static int cli_files_show(int fd, int argc, char *argv[])
 	int i;
 	struct mohclass *class;
 
-	ast_mutex_lock(&moh_lock);
-	for (class = mohclasses; class; class = class->next) {
+	AST_LIST_LOCK(&mohclasses);
+	AST_LIST_TRAVERSE(&mohclasses, class, list) {
 		if (!class->total_files)
 			continue;
 
@@ -1138,7 +1117,7 @@ static int cli_files_show(int fd, int argc, char *argv[])
 		for (i = 0; i < class->total_files; i++)
 			ast_cli(fd, "\tFile: %s\n", class->filearray[i]);
 	}
-	ast_mutex_unlock(&moh_lock);
+	AST_LIST_UNLOCK(&mohclasses);
 
 	return 0;
 }
@@ -1147,8 +1126,8 @@ static int moh_classes_show(int fd, int argc, char *argv[])
 {
 	struct mohclass *class;
 
-	ast_mutex_lock(&moh_lock);
-	for (class = mohclasses; class; class = class->next) {
+	AST_LIST_LOCK(&mohclasses);
+	AST_LIST_TRAVERSE(&mohclasses, class, list) {
 		ast_cli(fd, "Class: %s\n", class->name);
 		ast_cli(fd, "\tMode: %s\n", S_OR(class->mode,"<none>"));
 		ast_cli(fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
@@ -1156,7 +1135,7 @@ static int moh_classes_show(int fd, int argc, char *argv[])
 			ast_cli(fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
 		ast_cli(fd, "\tFormat: %s\n", ast_getformatname(class->format));
 	}
-	ast_mutex_unlock(&moh_lock);
+	AST_LIST_UNLOCK(&mohclasses);
 
 	return 0;
 }
@@ -1173,12 +1152,14 @@ static int init_classes(int reload)
     
 	if (!load_moh_classes(reload)) 		/* Load classes from config */
 		return 0;			/* Return if nothing is found */
-	moh = mohclasses;
-	while (moh) {
+
+	AST_LIST_LOCK(&mohclasses);
+	AST_LIST_TRAVERSE(&mohclasses, moh, list) {
 		if (moh->total_files)
 			moh_scan_files(moh);
-		moh = moh->next;
 	}
+	AST_LIST_UNLOCK(&mohclasses);
+
 	return 1;
 }