diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c
index 37e040e9b32d0966cc1d335bd2d27bce1c0b6c75..d01ea7aedfd1123482ad7c2397e277da77aaf173 100644
--- a/apps/app_dumpchan.c
+++ b/apps/app_dumpchan.c
@@ -75,6 +75,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
 			"CallerIDName=       %s\n"
 			"DNIDDigits=         %s\n"
 			"RDNIS=              %s\n"
+			"Parkinglot=         %s\n"
 			"Language=           %s\n"
 			"State=              %s (%d)\n"
 			"Rings=              %d\n"
@@ -103,6 +104,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
 			S_OR(c->cid.cid_name, "(N/A)"),
 			S_OR(c->cid.cid_dnid, "(N/A)"),
 			S_OR(c->cid.cid_rdnis, "(N/A)"),
+			c->parkinglot,
 			c->language,
 			ast_state2str(c->_state),
 			c->_state,
diff --git a/channels/chan_console.c b/channels/chan_console.c
index 7d62e6235c0e6aa8176193f23a903df11c7593d8..0fe3cbef4f2fade9eee0747e2e76162b30a943da 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -141,6 +141,8 @@ static struct console_pvt {
 		AST_STRING_FIELD(mohinterpret);
 		/*! Default language */
 		AST_STRING_FIELD(language);
+		/*! Default parkinglot */
+		AST_STRING_FIELD(parkinglot);
 	);
 	/*! Current channel for this device */
 	struct ast_channel *owner;
@@ -1004,6 +1006,7 @@ static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 		               "=== ---> CallerID Name:    %s\n"
 		               "=== ---> MOH Interpret:    %s\n"
 		               "=== ---> Language:         %s\n"
+		               "=== ---> Parkinglot:       %s\n"
 		               "=== ---> Muted:            %s\n"
 		               "=== ---> Auto-Answer:      %s\n"
 		               "=== ---> Override Context: %s\n"
@@ -1011,7 +1014,7 @@ static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 			pvt->name, (pvt == active_pvt) ? "Yes" : "No",
 			pvt->input_device, pvt->output_device, pvt->context,
 			pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
-			pvt->language, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
+			pvt->language, pvt->parkinglot, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
 			pvt->overridecontext ? "Yes" : "No");
 
 		console_pvt_unlock(pvt);
@@ -1236,6 +1239,7 @@ static void set_pvt_defaults(struct console_pvt *pvt)
 		ast_string_field_set(pvt, language, "");
 		ast_string_field_set(pvt, cid_num, "");
 		ast_string_field_set(pvt, cid_name, "");
+		ast_string_field_set(pvt, parkinglot, "");
 	
 		pvt->overridecontext = 0;
 		pvt->autoanswer = 0;
@@ -1248,6 +1252,7 @@ static void set_pvt_defaults(struct console_pvt *pvt)
 		ast_string_field_set(pvt, language, globals.language);
 		ast_string_field_set(pvt, cid_num, globals.cid_num);
 		ast_string_field_set(pvt, cid_name, globals.cid_name);
+		ast_string_field_set(pvt, parkinglot, globals.parkinglot);
 
 		pvt->overridecontext = globals.overridecontext;
 		pvt->autoanswer = globals.autoanswer;
@@ -1287,6 +1292,7 @@ static void store_config_core(struct console_pvt *pvt, const char *var, const ch
 	CV_F("callerid", store_callerid(pvt, value));
 	CV_BOOL("overridecontext", pvt->overridecontext);
 	CV_BOOL("autoanswer", pvt->autoanswer);
+	CV_STRFIELD("parkinglot", pvt, parkinglot);
 
 	if (pvt != &globals) {
 		CV_F("active", set_active(pvt, value))
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index fb58aa490eab659c015afac70f3125cac7961284..04ea60865e331bc676c3a341c8e3ca21c37a782f 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -142,6 +142,7 @@ struct gtalk {
 	int amaflags;			/*!< AMA Flags */
 	char user[AJI_MAX_JIDLEN];
 	char context[AST_MAX_CONTEXT];
+	char parkinglot[AST_MAX_CONTEXT];	/*!<  Parkinglot */
 	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Account code */
 	int capability;
 	ast_group_t callgroup;	/*!< Call group */
@@ -1024,6 +1025,8 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
 		ast_string_field_set(tmp, language, client->language);
 	if (!ast_strlen_zero(client->musicclass))
 		ast_string_field_set(tmp, musicclass, client->musicclass);
+	if (!ast_strlen_zero(client->parkinglot))
+		ast_string_field_set(tmp, parkinglot, client->parkinglot);
 	i->owner = tmp;
 	ast_module_ref(ast_module_info->self);
 	ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
@@ -1794,6 +1797,8 @@ static int gtalk_create_member(char *label, struct ast_variable *var, int allowg
 			ast_parse_allow_disallow(&member->prefs, &member->capability, var->value, 1);
 		else if (!strcasecmp(var->name, "context"))
 			ast_copy_string(member->context, var->value, sizeof(member->context));
+		else if (!strcasecmp(var->name, "parkinglot"))
+			ast_copy_string(member->parkinglot, var->value, sizeof(member->parkinglot));
 #if 0
 		else if (!strcasecmp(var->name, "candidate")) {
 			candidate = gtalk_create_candidate(var->value);
@@ -1832,6 +1837,7 @@ static int gtalk_load_config(void)
 	char *cat = NULL;
 	struct ast_config *cfg = NULL;
 	char context[AST_MAX_CONTEXT];
+	char parkinglot[AST_MAX_CONTEXT];
 	int allowguest = 1;
 	struct ast_variable *var;
 	struct gtalk *member;
@@ -1864,6 +1870,8 @@ static int gtalk_load_config(void)
 			ast_parse_allow_disallow(&prefs, &global_capability, var->value, 1);
 		else if (!strcasecmp(var->name, "context"))
 			ast_copy_string(context, var->value, sizeof(context));
+		else if (!strcasecmp(var->name, "parkinglot"))
+			ast_copy_string(parkinglot, var->value, sizeof(parkinglot));
 		else if (!strcasecmp(var->name, "bindaddr")) {
 			if (!(hp = ast_gethostbyname(var->value, &ahp))) {
 				ast_log(LOG_WARNING, "Invalid address: %s\n", var->value);
@@ -1892,6 +1900,7 @@ static int gtalk_load_config(void)
 				ast_copy_string(member->name, "guest", sizeof(member->name));
 				ast_copy_string(member->user, "guest", sizeof(member->user));
 				ast_copy_string(member->context, context, sizeof(member->context));
+				ast_copy_string(member->parkinglot, parkinglot, sizeof(member->parkinglot));
 				member->allowguest = allowguest;
 				member->prefs = prefs;
 				while (var) {
@@ -1904,6 +1913,9 @@ static int gtalk_load_config(void)
 					else if (!strcasecmp(var->name, "context"))
 						ast_copy_string(member->context, var->value,
 										sizeof(member->context));
+					else if (!strcasecmp(var->name, "parkinglot"))
+						ast_copy_string(member->parkinglot, var->value,
+										sizeof(member->parkinglot));
 /*  Idea to allow for custom candidates  */
 /*
 					else if (!strcasecmp(var->name, "candidate")) {
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index d9303405498ca0fda681020cb7d9e02f6e5b8aa4..c11fa1cd7ef4a7ecc1593f51034b220f78d01a1e 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -26,6 +26,8 @@
  * \arg \ref Config_iax
  *
  * \ingroup channel_drivers
+ * 
+ * \todo Implement musicclass settings for IAX2 devices
  */
 
 /*** MODULEINFO
@@ -140,6 +142,7 @@ static int trunk_timed, trunk_untimed, trunk_maxmtu, trunk_nmaxmtu ; 	/*!< Trunk
 
 
 static char context[80] = "default";
+static char default_parkinglot[AST_MAX_CONTEXT];
 
 static char language[MAX_LANGUAGE] = "";
 static char regcontext[AST_MAX_CONTEXT] = "";
@@ -298,6 +301,7 @@ struct iax2_user {
 		AST_STRING_FIELD(language);
 		AST_STRING_FIELD(cid_num);
 		AST_STRING_FIELD(cid_name);
+		AST_STRING_FIELD(parkinglot);           /*!< Default parkinglot for device */
 	);
 	
 	int authmethods;
@@ -333,6 +337,7 @@ struct iax2_peer {
 		AST_STRING_FIELD(cid_num);		/*!< Default context (for transfer really) */
 		AST_STRING_FIELD(cid_name);		/*!< Default context (for transfer really) */
 		AST_STRING_FIELD(zonetag);		/*!< Time Zone */
+		AST_STRING_FIELD(parkinglot);   /*!< Default parkinglot for device */
 	);
 	struct ast_codec_pref prefs;
 	struct ast_dnsmgr_entry *dnsmgr;		/*!< DNS refresh manager */
@@ -580,6 +585,8 @@ struct chan_iax2_pvt {
 		AST_STRING_FIELD(mohsuggest);
 		/*! received OSP token */
 		AST_STRING_FIELD(osptoken);
+		/*! Default parkinglot */
+		AST_STRING_FIELD(parkinglot);
 	);
 	
 	/*! permitted authentication methods */
@@ -1555,6 +1562,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
 			ast_string_field_set(iaxs[x], accountcode, accountcode);
 			ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
 			ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
+			ast_string_field_set(iaxs[x], parkinglot, default_parkinglot);
 		} else {
 			ast_log(LOG_WARNING, "Out of resources\n");
 			ast_mutex_unlock(&iaxsl[x]);
@@ -2437,6 +2445,7 @@ static char *handle_cli_iax2_show_peer(struct ast_cli_entry *e, int cmd, struct
 		ast_cli(a->fd, "  * Name       : %s\n", peer->name);
 		ast_cli(a->fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret) ? "<Not set>" : "<Set>");
 		ast_cli(a->fd, "  Context      : %s\n", peer->context);
+ 		ast_cli(a->fd, "  Parking lot  : %s\n", peer->parkinglot);
 		ast_cli(a->fd, "  Mailbox      : %s\n", peer->mailbox);
 		ast_cli(a->fd, "  Dynamic      : %s\n", ast_test_flag(peer, IAX_DYNAMIC) ? "Yes" : "No");
 		ast_cli(a->fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
@@ -3916,6 +3925,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
 	tmp->writeformat = ast_best_codec(capability);
 	tmp->tech_pvt = CALLNO_TO_PTR(i->callno);
 
+	if (!ast_strlen_zero(i->parkinglot))
+		ast_string_field_set(tmp, parkinglot, i->parkinglot);
 	/* Don't use ast_set_callerid() here because it will
 	 * generate a NewCallerID event before the NewChannel event */
 	if (!ast_strlen_zero(i->ani))
@@ -5739,6 +5750,8 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
 			ast_string_field_set(iaxs[callno], mohinterpret, user->mohinterpret);
 		if (!ast_strlen_zero(user->mohsuggest))
 			ast_string_field_set(iaxs[callno], mohsuggest, user->mohsuggest);
+		if (!ast_strlen_zero(user->parkinglot))
+			ast_string_field_set(iaxs[callno], parkinglot, user->parkinglot);
 		if (user->amaflags)
 			iaxs[callno]->amaflags = user->amaflags;
 		if (!ast_strlen_zero(user->language))
@@ -10421,6 +10434,8 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
 				ast_string_field_set(user, mohinterpret, v->value);
 			} else if (!strcasecmp(v->name, "mohsuggest")) {
 				ast_string_field_set(user, mohsuggest, v->value);
+			} else if (!strcasecmp(v->name, "parkinglot")) {
+				ast_string_field_set(user, parkinglot, v->value);
 			} else if (!strcasecmp(v->name, "language")) {
 				ast_string_field_set(user, language, v->value);
 			} else if (!strcasecmp(v->name, "amaflags")) {
@@ -10622,6 +10637,8 @@ static int set_config(char *config_file, int reload)
 #ifdef SO_NO_CHECK
 	nochecksums = 0;
 #endif
+	/* Reset default parking lot */
+	default_parkinglot[0] = '\0';
 
 	min_reg_expire = IAX_DEFAULT_REG_EXPIRE;
 	max_reg_expire = IAX_DEFAULT_REG_EXPIRE;
@@ -10818,6 +10835,8 @@ static int set_config(char *config_file, int reload)
 		} else if (!strcasecmp(v->name, "cos")) {
 			if (ast_str2cos(v->value, &cos))
 				ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
+		} else if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(default_parkinglot, v->value, sizeof(default_parkinglot));
 		} else if (!strcasecmp(v->name, "accountcode")) {
 			ast_copy_string(accountcode, v->value, sizeof(accountcode));
 		} else if (!strcasecmp(v->name, "mohinterpret")) {
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index 52a4693e072b36bb2ba54bfa9b8e145cfe0c2b98..7285549162361ec3a7828eb8b9bf3e749ddbbae8 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -151,6 +151,7 @@ struct jingle {
 	int allowguest;
 	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
 	char musicclass[MAX_MUSICCLASS];	/*!<  Music on Hold class */
+	char parkinglot[AST_MAX_CONTEXT];   /*!< Parkinglot */
 };
 
 struct jingle_container {
@@ -1741,6 +1742,9 @@ static int jingle_load_config(void)
 					else if (!strcasecmp(var->name, "context"))
 						ast_copy_string(member->context, var->value,
 										sizeof(member->context));
+					else if (!strcasecmp(var->name, "parkinglot"))
+						ast_copy_string(member->parkinglot, var->value,
+										sizeof(member->parkinglot));
 /*  Idea to allow for custom candidates  */
 /*
 					else if (!strcasecmp(var->name, "candidate")) {
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index f18dac361de11630b84713ded30355e31e93dc80..021999abdf44e37738e15162c05946b24341d690 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -143,6 +143,7 @@ static char context[AST_MAX_EXTENSION] = "default";
 
 static char language[MAX_LANGUAGE] = "";
 static char musicclass[MAX_MUSICCLASS] = "";
+static char parkinglot[AST_MAX_CONTEXT];
 static char cid_num[AST_MAX_EXTENSION] = "";
 static char cid_name[AST_MAX_EXTENSION] = "";
 
@@ -317,6 +318,7 @@ struct mgcp_endpoint {
 	char musicclass[MAX_MUSICCLASS];
 	char curtone[80];			/*!< Current tone */
 	char mailbox[AST_MAX_EXTENSION];
+	char parkinglot[AST_MAX_CONTEXT];   /*!< Parkinglot */
 	struct ast_event_sub *mwi_event_sub;
 	ast_group_t callgroup;
 	ast_group_t pickupgroup;
@@ -3685,6 +3687,8 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
 				}
 			} else if (!strcasecmp(v->name, "musiconhold")) {
 				ast_copy_string(musicclass, v->value, sizeof(musicclass));
+			} else if (!strcasecmp(v->name, "parkinglot")) {
+				ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
 			} else if (!strcasecmp(v->name, "callgroup")) {
 				cur_callergroup = ast_get_group(v->value);
 			} else if (!strcasecmp(v->name, "pickupgroup")) {
@@ -3748,6 +3752,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
 					ast_copy_string(e->language, language, sizeof(e->language));
 					ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
 					ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
+					ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
 					if (!ast_strlen_zero(e->mailbox)) {
 						char *mailbox, *context;
 						context = mailbox = ast_strdupa(e->mailbox);
@@ -3856,6 +3861,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
 					ast_copy_string(e->language, language, sizeof(e->language));
 					ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
 					ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
+					ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
 					if (!ast_strlen_zero(mailbox)) {
 						ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
 					}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 79fc483990b98cc616bd1f87362a3ab08a43a8fa..31bd5763d3167a08259e66bc74b0cb55a0a31582 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -663,6 +663,7 @@ static char default_vmexten[AST_MAX_EXTENSION];
 static char default_mohinterpret[MAX_MUSICCLASS];  /*!< Global setting for moh class to use when put on hold */
 static char default_mohsuggest[MAX_MUSICCLASS];	   /*!< Global setting for moh class to suggest when putting 
                                                     *   a bridged channel on hold */
+static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
 static int default_maxcallbitrate;	/*!< Maximum bitrate for call */
 static struct ast_codec_pref default_prefs;		/*!< Default codec prefs */
 
@@ -1219,6 +1220,7 @@ struct sip_pvt {
 		AST_STRING_FIELD(rpid);		/*!< Our RPID header */
 		AST_STRING_FIELD(rpid_from);	/*!< Our RPID From header */
 		AST_STRING_FIELD(url);		/*!< URL to be sent with next message to peer */
+		AST_STRING_FIELD(parkinglot);		/*!< Parkinglot */
 	);
 	struct sip_socket socket;		/*!< The socket used for this dialog */
 	unsigned int ocseq;			/*!< Current outgoing seqno */
@@ -1405,6 +1407,7 @@ struct sip_user {
 	char language[MAX_LANGUAGE];	/*!< Default language for this user */
 	char mohinterpret[MAX_MUSICCLASS];/*!< Music on Hold class */
 	char mohsuggest[MAX_MUSICCLASS];/*!< Music on Hold class */
+	char parkinglot[AST_MAX_CONTEXT];/*!< Parkinglot */
 	char useragent[256];		/*!< User agent in SIP request */
 	struct ast_codec_pref prefs;	/*!< codec prefs */
 	ast_group_t callgroup;		/*!< Call group */
@@ -1474,6 +1477,7 @@ struct sip_peer {
 	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
 	char mohinterpret[MAX_MUSICCLASS];/*!<  Music on Hold class */
 	char mohsuggest[MAX_MUSICCLASS];/*!<  Music on Hold class */
+	char parkinglot[AST_MAX_CONTEXT];/*!<  Parkinglot */
 	char useragent[256];		/*!<  User agent in SIP request (saved from registration) */
 	struct ast_codec_pref prefs;	/*!<  codec prefs */
 	int lastmsgssent;
@@ -4246,6 +4250,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
 	ast_string_field_set(dialog, tohost, peer->tohost);
 	ast_string_field_set(dialog, fullcontact, peer->fullcontact);
 	ast_string_field_set(dialog, context, peer->context);
+	ast_string_field_set(dialog, parkinglot, peer->parkinglot);
 	dialog->outboundproxy = obproxy_get(dialog, peer);
 	dialog->callgroup = peer->callgroup;
 	dialog->pickupgroup = peer->pickupgroup;
@@ -6076,6 +6081,7 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
 		p->t38.jointcapability = p->t38.capability;
 	}
 	ast_string_field_set(p, context, default_context);
+	ast_string_field_set(p, parkinglot, default_parkinglot);
 
 
 	/* Add to active dialog list */
@@ -11578,6 +11584,7 @@ static enum check_auth_result check_user_ok(struct sip_pvt *p, char *of,
 		ast_string_field_set(p, language, user->language);
 		ast_string_field_set(p, mohsuggest, user->mohsuggest);
 		ast_string_field_set(p, mohinterpret, user->mohinterpret);
+		ast_string_field_set(p, parkinglot, user->parkinglot);
 		p->allowtransfer = user->allowtransfer;
 		p->amaflags = user->amaflags;
 		p->callgroup = user->callgroup;
@@ -11665,6 +11672,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
 	ast_string_field_set(p, subscribecontext, peer->subscribecontext);
 	ast_string_field_set(p, mohinterpret, peer->mohinterpret);
 	ast_string_field_set(p, mohsuggest, peer->mohsuggest);
+	ast_string_field_set(p, parkinglot, peer->parkinglot);
 	if (peer->callingpres)	/* Peer calling pres setting will override RPID */
 		p->callingpres = peer->callingpres;
 	if (peer->maxms && peer->lastms)
@@ -20484,6 +20492,8 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, str
 			user->callgroup = ast_get_group(v->value);
 		} else if (!strcasecmp(v->name, "pickupgroup")) {
 			user->pickupgroup = ast_get_group(v->value);
+		} else if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(user->parkinglot, v->value, sizeof(user->parkinglot));
 		} else if (!strcasecmp(v->name, "language")) {
 			ast_copy_string(user->language, v->value, sizeof(user->language));
 		} else if (!strcasecmp(v->name, "mohinterpret")) {
@@ -20861,6 +20871,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
 			ast_copy_string(peer->mohinterpret, v->value, sizeof(peer->mohinterpret));
 		} else if (!strcasecmp(v->name, "mohsuggest")) {
 			ast_copy_string(peer->mohsuggest, v->value, sizeof(peer->mohsuggest));
+		} else if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(peer->parkinglot, v->value, sizeof(peer->parkinglot));
 		} else if (!strcasecmp(v->name, "mailbox")) {
 			add_peer_mailboxes(peer, v->value);
 		} else if (!strcasecmp(v->name, "subscribemwi")) {
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 198b464068ea22fc0fd8251ee0f5ab62ca5fd463..c4458ba04e879f4a4e9dd694f4b1ac2c62ac6df2 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -968,6 +968,7 @@ static char mohsuggest[MAX_MUSICCLASS] = "";
 static char cid_num[AST_MAX_EXTENSION] = "";
 static char cid_name[AST_MAX_EXTENSION] = "";
 static char linelabel[AST_MAX_EXTENSION] ="";
+static char parkinglot[AST_MAX_CONTEXT] ="";
 static int nat = 0;
 static ast_group_t cur_callergroup = 0;
 static ast_group_t cur_pickupgroup = 0;
@@ -1162,6 +1163,7 @@ struct skinny_line {
 	char vmexten[AST_MAX_EXTENSION];
 	char regexten[AST_MAX_EXTENSION];		/* Extension for auto-extensions */
 	char regcontext[AST_MAX_CONTEXT];		/* Context for auto-extensions */
+	char parkinglot[AST_MAX_CONTEXT];		/* Parkinglot for parkedcalls */
 	char mohinterpret[MAX_MUSICCLASS];
 	char mohsuggest[MAX_MUSICCLASS];
 	char lastnumberdialed[AST_MAX_EXTENSION];	/* Last number that was dialed - used for redial */
@@ -3024,6 +3026,8 @@ static struct skinny_device *build_device(const char *cat, struct ast_variable *
 				ast_copy_string(linelabel, v->value, sizeof(linelabel));
 			} else if (!strcasecmp(v->name, "setvar")) {
 				chanvars = add_var(v->value, chanvars);
+			} else if ( !strcasecmp(v->name, "parkinglot")) {
+				ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
 			} else if (!strcasecmp(v->name, "speeddial")) {
 				if (!(sd = ast_calloc(1, sizeof(*sd)))) {
 					return NULL;
@@ -3077,6 +3081,7 @@ static struct skinny_device *build_device(const char *cat, struct ast_variable *
 					ast_copy_string(l->cid_num, cid_num, sizeof(l->cid_num));
 					ast_copy_string(l->cid_name, cid_name, sizeof(l->cid_name));
 					ast_copy_string(l->label, linelabel, sizeof(l->label));
+					ast_copy_string(l->parkinglot, parkinglot, sizeof(l->parkinglot));
 					ast_copy_string(l->language, language, sizeof(l->language));
 					ast_copy_string(l->mohinterpret, mohinterpret, sizeof(l->mohinterpret));
 					ast_copy_string(l->mohsuggest, mohsuggest, sizeof(l->mohsuggest));
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index 88f37fbec175f8e14f9db98d67d33c9f349a9689..7318e7353d34cda22c0e69261ff763f86524aed7 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -404,6 +404,8 @@ struct unistim_line {
 	int amaflags;
 	/*! Codec supported */
 	int capability;
+	/*! Parkinglot */
+	char parkinglot[AST_MAX_CONTEXT];
 	struct unistim_line *next;
 	struct unistim_device *parent;
 };
@@ -5111,6 +5113,8 @@ static struct unistim_device *build_device(const char *cat, const struct ast_var
 			l->pickupgroup = ast_get_group(v->value);
 		else if (!strcasecmp(v->name, "mailbox"))
 			ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
+		else if (!strcasecmp(v->name, "parkinglot"))
+			ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
 		else if (!strcasecmp(v->name, "linelabel"))
 			unquote(linelabel, v->value, sizeof(linelabel) - 1);
 		else if (!strcasecmp(v->name, "extension")) {
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index def1015f87fa5a612853b4b3790651883d93ecbf..927275d8b77cd4b92a1865747691aa798d664886 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -237,6 +237,8 @@ static const char config[] = "zapata.conf";
 static char defaultcic[64] = "";
 static char defaultozz[64] = "";
 
+static char parkinglot[AST_MAX_EXTENSION] = "";		/*!< Default parking lot for this channel */
+
 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
 static char mwimonitornotify[PATH_MAX] = "";
 
@@ -595,6 +597,7 @@ static struct zt_pvt {
 	char language[MAX_LANGUAGE];
 	char mohinterpret[MAX_MUSICCLASS];
 	char mohsuggest[MAX_MUSICCLASS];
+	char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
 #if defined(PRI_ANI) || defined(HAVE_SS7)
 	char cid_ani[AST_MAX_EXTENSION];
 #endif
@@ -777,6 +780,7 @@ static struct zt_chan_conf zt_chan_conf_default(void) {
 			.cid_name = "",
 			.mohinterpret = "default",
 			.mohsuggest = "",
+			.parkinglot = "",
 			.transfertobusy = 1,
 
 			.cid_signalling = CID_SIG_BELL,
@@ -5963,6 +5967,8 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
 		tmp->callgroup = i->callgroup;
 		tmp->pickupgroup = i->pickupgroup;
 	}
+	if (!ast_strlen_zero(i->parkinglot))
+		ast_string_field_set(tmp, parkinglot, i->parkinglot);
 	if (!ast_strlen_zero(i->language))
 		ast_string_field_set(tmp, language, i->language);
 	if (!i->owner)
@@ -8077,6 +8083,7 @@ static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pr
 	struct zt_bufferinfo bi;
 #endif
 	struct zt_spaninfo si;
+
 	int res;
 	int span=0;
 	int here = 0;
@@ -8493,6 +8500,7 @@ static struct zt_pvt *mkintf(int channel, struct zt_chan_conf conf, struct zt_pr
 		ast_copy_string(tmp->mohsuggest, conf.chan.mohsuggest, sizeof(tmp->mohsuggest));
 		ast_copy_string(tmp->context, conf.chan.context, sizeof(tmp->context));
 		ast_copy_string(tmp->cid_num, conf.chan.cid_num, sizeof(tmp->cid_num));
+		ast_copy_string(tmp->parkinglot, conf.chan.parkinglot, sizeof(tmp->parkinglot));
 		tmp->cid_ton = 0;
 		ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
 		ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
@@ -13258,12 +13266,17 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
 	const char *ringc; /* temporary string for parsing the dring number. */
 	int y;
 	int found_pseudo = 0;
-        char zapchan[MAX_CHANLIST_LEN] = {};
+	char zapchan[MAX_CHANLIST_LEN] = {};
 
 	for (; v; v = v->next) {
 		if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
 			continue;
 
+		/* must have parkinglot in confp before build_channels is called */
+		if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
+		}
+
 		/* Create the interface list */
 		if (!strcasecmp(v->name, "channel")
 #ifdef HAVE_PRI
@@ -13424,6 +13437,8 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
 			ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
 		} else if (!strcasecmp(v->name, "mohsuggest")) {
 			ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
+		} else if (!strcasecmp(v->name, "parkinglot")) {
+			ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
 		} else if (!strcasecmp(v->name, "stripmsd")) {
 			ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
 			confp->chan.stripmsd = atoi(v->value);
diff --git a/configs/features.conf.sample b/configs/features.conf.sample
index 3666e804b2988d9c83bc56a77fe199be22b71ecc..6e833891fe9f37cbfea2afd9a56aeee9707a53ce 100644
--- a/configs/features.conf.sample
+++ b/configs/features.conf.sample
@@ -3,10 +3,11 @@
 ;
 
 [general]
-parkext => 700			; What extension to dial to park
-parkpos => 701-720		; What extensions to park calls on. These needs to be
-				; numeric, as Asterisk starts from the start position
+parkext => 700			; What extension to dial to park	(all parking lots)
+parkpos => 701-720		; What extensions to park calls on. (defafult parking lot)
+				; These needs to be numeric, as Asterisk starts from the start position
 				; and increments with one for the next parked call.
+context => parkedcalls		; Which context parked calls are in (default parking lot)
 context => parkedcalls		; Which context parked calls are in
 ;parkingtime => 45		; Number of seconds a call can be parked for 
 				; (default is 45 seconds)
@@ -46,6 +47,7 @@ context => parkedcalls		; Which context parked calls are in
 ; They can not be used while the remote party is ringing or in progress. If you require this feature you can use
 ; chan_local in combination with Answer to accomplish it.
 
+
 [featuremap]
 ;blindxfer => #1		; Blind transfer  (default is #)
 ;disconnect => *0		; Disconnect  (default is *)
@@ -87,6 +89,7 @@ context => parkedcalls		; Which context parked calls are in
 ;                   channel waits for the feature to complete. If left blank,
 ;                   no music will be played.
 ;
+
 ;
 ; IMPORTANT NOTE: The applicationmap is not intended to be used for all Asterisk
 ;   applications. When applications are used in extensions.conf, they are executed
@@ -108,20 +111,21 @@ context => parkedcalls		; Which context parked calls are in
 ;unpauseMonitor => #3,self/callee,UnPauseMonitor   ;Allow the callee to unpause monitoring
 ;                                                  ;on their channel
 ;
+;*** Define another parking lot
+;
+; You can set parkinglot with the CHANNEL dialplan function
+; or configure it in the device configuration in the channel
+;
+;[parkinglot_edvina]
+;context => edvinapark
+;parkpos => 800-850
+;findslot => next
+
 ; GROUPS
 ;   Groups are groupings of features defined in [applicationmap]
 ;   that can have their own key mappings.
 ;
-;   Groups are defined as a configuration section,
-;   and can be set as part of DYNAMIC_FEATURES in
-;   the same way that a normal feature can... 
-;	etc:	
-;
-;	  Set(DYNAMIC_FEATURES=myGroupName);
-;
 ; example:
 ; [myGroupName]        ; defines the group named myGroupName
 ; testfeature => #9    ; associates testfeature with the group and the keycode #9
 ; pauseMonitor         ; associates pauseMonitor with the group and the keycode
-;                      ; defined in [applicationmap]
-
diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample
index 2441f2cf4288904278eb51dcbc6fa722893c6664..105940060d6b0bdf17069e713dc3a4fa9040eae3 100644
--- a/configs/iax.conf.sample
+++ b/configs/iax.conf.sample
@@ -286,6 +286,10 @@ autokill=yes
 			; has expired based on its registration interval, used the stored
 			; address information regardless. (yes|no)
 
+;parkinglot=edvina		; Default parkinglot for IAX peers and users
+				; This can also be configured per device
+				; Parkinglots are defined in features.conf
+
 ; Guest sections for unauthenticated connection attempts.  Just specify an
 ; empty secret, or provide no secret section.
 ;
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 10293a77ca1e70a11ee51e3b88ea55b0585a5be7..7a3d114605c2ccea13233b9709751c3ddb9986ab 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -195,6 +195,9 @@ srvlookup=yes			; Enable DNS SRV lookups on outbound calls
 ;
 ;mohsuggest=default
 ;
+;parkinglot=plaza		; Sets the default parking lot for call parking
+				; This may also be set for individual users/peers
+				; Parkinglots are configured in features.conf
 ;language=en			; Default language setting for all users/peers
 				; This may also be set for individual users/peers
 ;relaxdtmf=yes			; Relax dtmf handling
diff --git a/funcs/func_channel.c b/funcs/func_channel.c
index 42b3c68c9f7e64b3b5f6755f9c57e774a9e2a2ba..8388d7fa6d2e644996e364cd819d9906fd5a892c 100644
--- a/funcs/func_channel.c
+++ b/funcs/func_channel.c
@@ -84,6 +84,8 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
 		locked_copy_string(chan, buf, chan->language, len);
 	else if (!strcasecmp(data, "musicclass"))
 		locked_copy_string(chan, buf, chan->musicclass, len);
+	else if (!strcasecmp(data, "parkinglot"))
+		locked_copy_string(chan, buf, chan->parkinglot, len);
 	else if (!strcasecmp(data, "state"))
 		locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
 	else if (!strcasecmp(data, "channeltype"))
@@ -110,6 +112,8 @@ static int func_channel_write(struct ast_channel *chan, const char *function,
 
 	if (!strcasecmp(data, "language"))
 		locked_string_field_set(chan, language, value);
+	else if (!strcasecmp(data, "parkinglot"))
+		locked_string_field_set(chan, parkinglot, value);
 	else if (!strcasecmp(data, "musicclass"))
 		locked_string_field_set(chan, musicclass, value);
 #ifdef CHANNEL_TRACE
@@ -172,6 +176,7 @@ static struct ast_custom_function channel_function = {
 		"R/O	channeltype        technology used for channel\n"
 		"R/W	language           language for sounds played\n"
 		"R/W	musicclass         class (from musiconhold.conf) for hold music\n"
+		"R/W	parkinglot         parkinglot for parking\n"
 		"R/W	rxgain             set rxgain level on channel drivers that support it\n"
 		"R/O	state              state for channel\n"
 		"R/W	tonezone           zone for indications played\n"
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index ddba96f8942b0e05de1ca33a9331a059e25adf15..e0b1f79bb58eb0d56fc45cbb87454c5f8a77bf59 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -434,6 +434,7 @@ struct ast_channel {
 		AST_STRING_FIELD(accountcode);		/*!< Account code for billing */
 		AST_STRING_FIELD(call_forward);		/*!< Where to forward to if asked to dial on this interface */
 		AST_STRING_FIELD(uniqueid);		/*!< Unique Channel Identifier */
+		AST_STRING_FIELD(parkinglot);		/*! Default parking lot, if empty, default parking lot  */
 	);
 	
 	int fds[AST_MAX_FDS];				/*!< File descriptors for channel -- Drivers will poll on
diff --git a/main/features.c b/main/features.c
index 089f27a0fe75a8e2e5e877320d50d2102d94e8df..59e2d9a58bd4229df32519c9d75e50c4db6bfc06 100644
--- a/main/features.c
+++ b/main/features.c
@@ -54,11 +54,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/monitor.h"
 #include "asterisk/audiohook.h"
 #include "asterisk/global_datastores.h"
+#include "asterisk/astobj2.h"
 
 #define DEFAULT_PARK_TIME 45000
 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
 #define DEFAULT_FEATURE_DIGIT_TIMEOUT 500
 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
+#define DEFAULT_PARKINGLOT "default"			/*!< Default parking lot */
 #define DEFAULT_ATXFER_DROP_CALL 0
 #define DEFAULT_ATXFER_LOOP_DELAY 10000
 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
@@ -85,26 +87,55 @@ static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
 
 static char *parkedcall = "ParkedCall";
 
-static int parkaddhints = 0;                               /*!< Add parking hints automatically */
-static int parkedcalltransfers = 0;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
-static int parkedcallreparking = 0;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
-static int parkingtime = DEFAULT_PARK_TIME;                /*!< No more than 45 seconds parked before you do something with them */
-static char parking_con[AST_MAX_EXTENSION];                /*!< Context for which parking is made accessible */
-static char parking_con_dial[AST_MAX_EXTENSION];           /*!< Context for dialback for parking (KLUDGE) */
-static char parking_ext[AST_MAX_EXTENSION];                /*!< Extension you type to park the call */
 static char pickup_ext[AST_MAX_EXTENSION];                 /*!< Call pickup extension */
-static char parkmohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
-static int parking_start;                                  /*!< First available extension for parking */
-static int parking_stop;                                   /*!< Last available extension for parking */
+
+/*! \brief Description of one parked call, added to a list while active, then removed.
+	The list belongs to a parkinglot 
+*/
+struct parkeduser {
+	struct ast_channel *chan;                   /*!< Parking channel */
+	struct timeval start;                       /*!< Time the parking started */
+	int parkingnum;                             /*!< Parking lot */
+	char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
+	char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
+	char exten[AST_MAX_EXTENSION];
+	int priority;
+	int parkingtime;                            /*!< Maximum length in parking lot before return */
+	int notquiteyet;
+	char peername[1024];
+	unsigned char moh_trys;
+	struct ast_parkinglot *parkinglot;
+	AST_LIST_ENTRY(parkeduser) list;
+};
+
+/*! \brief Structure for parking lots which are put in a container. */
+struct ast_parkinglot {
+	char name[AST_MAX_CONTEXT];
+	char parking_con[AST_MAX_EXTENSION];		/*!< Context for which parking is made accessible */
+	char parking_con_dial[AST_MAX_EXTENSION];	/*!< Context for dialback for parking (KLUDGE) */
+	int parking_start;				/*!< First available extension for parking */
+	int parking_stop;				/*!< Last available extension for parking */
+	int parking_offset;
+	int parkfindnext;
+	int parkingtime;				/*!< Default parking time */
+	char mohclass[MAX_MUSICCLASS];                  /*!< Music class used for parking */
+	int parkaddhints;                               /*!< Add parking hints automatically */
+	int parkedcalltransfers;                        /*!< Enable DTMF based transfers on bridge when picking up parked calls */
+	int parkedcallreparking;                        /*!< Enable DTMF based parking on bridge when picking up parked calls */
+	AST_LIST_HEAD(parkinglot_parklist, parkeduser) parkings; /*!< List of active parkings in this parkinglot */
+};
+
+/*! \brief The list of parking lots configured. Always at least one  - the default parking lot */
+static struct ao2_container *parkinglots;
+ 
+struct ast_parkinglot *default_parkinglot;
+char parking_ext[AST_MAX_EXTENSION];            /*!< Extension you type to park the call */
 
 static char courtesytone[256];                             /*!< Courtesy tone */
 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
 static char xfersound[256];                                /*!< Call transfer sound */
 static char xferfailsound[256];                            /*!< Call transfer failure sound */
 
-static int parking_offset;
-static int parkfindnext;
-
 static int adsipark;
 
 static int transferdigittimeout;
@@ -152,24 +183,15 @@ static int mixmonitor_ok = 1;
 static struct ast_app *stopmixmonitor_app = NULL;
 static int stopmixmonitor_ok = 1;
 
-struct parkeduser {
-	struct ast_channel *chan;                   /*!< Parking channel */
-	struct timeval start;                       /*!< Time the parking started */
-	int parkingnum;                             /*!< Parking lot */
-	char parkingexten[AST_MAX_EXTENSION];       /*!< If set beforehand, parking extension used for this call */
-	char context[AST_MAX_CONTEXT];              /*!< Where to go if our parking time expires */
-	char exten[AST_MAX_EXTENSION];
-	int priority;
-	int parkingtime;                            /*!< Maximum length in parking lot before return */
-	int notquiteyet;
-	char peername[1024];
-	unsigned char moh_trys;
-	AST_LIST_ENTRY(parkeduser) list;
-};
+static pthread_t parking_thread;
 
-static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
+/* Forward declarations */
+static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot);
+static void parkinglot_unref(struct ast_parkinglot *parkinglot);
+static void parkinglot_destroy(void *obj);
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
+struct ast_parkinglot *find_parkinglot(const char *name);
 
-static pthread_t parking_thread;
 
 const char *ast_parking_ext(void)
 {
@@ -189,7 +211,17 @@ struct ast_bridge_thread_obj
 	unsigned int return_to_pbx:1;
 };
 
+static int parkinglot_hash_cb(const void *obj, const int flags)
+{
+	const struct ast_parkinglot *parkinglot = obj;
+	return ast_str_hash(parkinglot->name);
+}
 
+static int parkinglot_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct ast_parkinglot *parkinglot = obj, *parkinglot2 = arg;
+	return !strcasecmp(parkinglot->name, parkinglot2->name) ? CMP_MATCH : 0;
+}
 
 /*!
  * \brief store context, extension and priority 
@@ -345,6 +377,23 @@ static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
 	return ast_adsi_print(chan, message, justify, 1);
 }
 
+/*! \brief Find parking lot name from channel */
+static const char *findparkinglotname(struct ast_channel *chan)
+{
+	const char *temp, *parkinglot = NULL;
+
+	/* Check if the channel has a parking lot */
+	if (!ast_strlen_zero(chan->parkinglot))
+		parkinglot = chan->parkinglot;
+
+	/* Channel variables override everything */
+
+	if ((temp  = pbx_builtin_getvar_helper(chan, "PARKINGLOT")))
+		return temp;
+
+	return parkinglot;
+}
+
 /*! \brief Notify metermaids that we've changed an extension */
 static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
 {
@@ -375,36 +424,54 @@ static enum ast_device_state metermaidstate(const char *data)
 }
 
 /* Park a call */
-static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name)
+static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, char *orig_chan_name, struct ast_parkinglot *parkinglot)
 {
 	struct parkeduser *pu, *cur;
 	int i, x = -1, parking_range;
 	struct ast_context *con;
+	const char *parkinglotname;
 	const char *parkingexten;
 	
+	parkinglotname = findparkinglotname(peer);
+
+	if (parkinglotname) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
+		parkinglot = find_parkinglot(parkinglotname);	
+	}
+	if (!parkinglot)
+		parkinglot = default_parkinglot;
+
+	parkinglot_addref(parkinglot);
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Parkinglot: %s\n", parkinglot->name);
+
 	/* Allocate memory for parking data */
-	if (!(pu = ast_calloc(1, sizeof(*pu)))) 
+	if (!(pu = ast_calloc(1, sizeof(*pu)))) {
+		parkinglot_unref(parkinglot);
 		return -1;
+	}
 
-	/* Lock parking lot */
-	AST_LIST_LOCK(&parkinglot);
+	/* Lock parking list */
+	AST_LIST_LOCK(&parkinglot->parkings);
 	/* Check for channel variable PARKINGEXTEN */
 	parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
 	if (!ast_strlen_zero(parkingexten)) {
-		if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
-			AST_LIST_UNLOCK(&parkinglot);
+		if (ast_exists_extension(NULL, parkinglot->parking_con, parkingexten, 1, NULL)) {
+			AST_LIST_UNLOCK(&parkinglot->parkings);
+			parkinglot_unref(parkinglot);
 			ast_free(pu);
-			ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
+			ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parkinglot->parking_con);
 			return 1;	/* Continue execution if possible */
 		}
 		ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
 		x = atoi(parkingexten);
 	} else {
 		/* Select parking space within range */
-		parking_range = parking_stop - parking_start+1;
+		parking_range = parkinglot->parking_stop - parkinglot->parking_start+1;
 		for (i = 0; i < parking_range; i++) {
-			x = (i + parking_offset) % parking_range + parking_start;
-			AST_LIST_TRAVERSE(&parkinglot, cur, list) {
+			x = (i + parkinglot->parking_offset) % parking_range + parkinglot->parking_start;
+			AST_LIST_TRAVERSE(&parkinglot->parkings, cur, list) {
 				if (cur->parkingnum == x)
 					break;
 			}
@@ -415,12 +482,13 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 		if (!(i < parking_range)) {
 			ast_log(LOG_WARNING, "No more parking spaces\n");
 			ast_free(pu);
-			AST_LIST_UNLOCK(&parkinglot);
+			AST_LIST_UNLOCK(&parkinglot->parkings);
+			parkinglot_unref(parkinglot);
 			return -1;
 		}
 		/* Set pointer for next parking */
-		if (parkfindnext) 
-			parking_offset = x - parking_start + 1;
+		if (parkinglot->parkfindnext) 
+			parkinglot->parking_offset = x - parkinglot->parking_start + 1;
 	}
 	
 	chan->appl = "Parked Call";
@@ -431,13 +499,14 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 	/* Put the parked channel on hold if we have two different channels */
 	if (chan != peer) {
 		ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
-			S_OR(parkmohclass, NULL),
-			!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
+			S_OR(parkinglot->mohclass, NULL),
+			!ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
 	}
 	
 	pu->start = ast_tvnow();
 	pu->parkingnum = x;
-	pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
+	pu->parkinglot = parkinglot;
+	pu->parkingtime = (timeout > 0) ? timeout : parkinglot->parkingtime;
 	if (extout)
 		*extout = x;
 
@@ -449,26 +518,28 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 	ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
 	ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
 	pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
-	AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
+	AST_LIST_INSERT_TAIL(&parkinglot->parkings, pu, list);
 
 	/* If parking a channel directly, don't quiet yet get parking running on it */
 	if (peer == chan) 
 		pu->notquiteyet = 1;
-	AST_LIST_UNLOCK(&parkinglot);
+	AST_LIST_UNLOCK(&parkinglot->parkings);
+
 	/* Wake up the (presumably select()ing) thread */
 	pthread_kill(parking_thread, SIGURG);
-	ast_verb(2, "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
+	ast_verb(2, "Parked %s on %d (lot %s). Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parkinglot->name, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
 
 	if (pu->parkingnum != -1)
 		snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
 	manager_event(EVENT_FLAG_CALL, "ParkedCall",
 		"Exten: %s\r\n"
 		"Channel: %s\r\n"
+		"Parkinglot: %s\r\n"
 		"From: %s\r\n"
 		"Timeout: %ld\r\n"
 		"CallerIDNum: %s\r\n"
 		"CallerIDName: %s\r\n",
-		pu->parkingexten, pu->chan->name, peer ? peer->name : "",
+		pu->parkingexten, pu->chan->name, pu->parkinglot->name, peer ? peer->name : "",
 		(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
 		S_OR(pu->chan->cid.cid_num, "<unknown>"),
 		S_OR(pu->chan->cid.cid_name, "<unknown>")
@@ -479,9 +550,9 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 		ast_adsi_unload_session(peer);
 	}
 
-	con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
+	con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar);
 	if (!con)	/* Still no context? Bad */
-		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
 	/* Tell the peer channel the number of the parking space */
 	if (peer && ((pu->parkingnum != -1 && ast_strlen_zero(orig_chan_name)) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
 		/* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
@@ -491,13 +562,13 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 	}
 	if (con) {
 		if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
-			notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
+			notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_INUSE);
 	}
 	if (pu->notquiteyet) {
 		/* Wake up parking thread if we're really done */
 		ast_indicate_data(pu->chan, AST_CONTROL_HOLD, 
-			S_OR(parkmohclass, NULL),
-			!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
+			S_OR(parkinglot->mohclass, NULL),
+			!ast_strlen_zero(parkinglot->mohclass) ? strlen(parkinglot->mohclass) + 1 : 0);
 		pu->notquiteyet = 0;
 		pthread_kill(parking_thread, SIGURG);
 	}
@@ -507,7 +578,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
 /*! \brief Park a call */
 int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
 {
-	return park_call_full(chan, peer, timeout, extout, NULL);
+	return park_call_full(chan, peer, timeout, extout, NULL, NULL);
 }
 
 /* Park call via masquraded channel */
@@ -537,7 +608,7 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
 
 	orig_chan_name = ast_strdupa(chan->name);
 
-	park_call_full(chan, peer, timeout, extout, orig_chan_name);
+	park_call_full(chan, peer, timeout, extout, orig_chan_name, NULL);
 
 	return 0;
 }
@@ -742,12 +813,12 @@ static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *
 	count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
 	ast_channel_unlock(callee_chan);
 
-	// This means a mixmonitor is attached to the channel, running or not is unknown.
+	/* This means a mixmonitor is attached to the channel, running or not is unknown. */
 	if (count > 0) {
 		
 		ast_verb(3, "User hit '%s' to stop recording call.\n", code);
 
-		//Make sure they are running
+		/* Make sure they are running */
 		ast_channel_lock(callee_chan);
 		count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
 		ast_channel_unlock(callee_chan);
@@ -2165,186 +2236,208 @@ static void post_manager_event(const char *s, struct parkeduser *pu)
 	manager_event(EVENT_FLAG_CALL, s,
 		"Exten: %s\r\n"
 		"Channel: %s\r\n"
+		"Parkinglot: %s\r\n"
 		"CallerIDNum: %s\r\n"
 		"CallerIDName: %s\r\n\r\n",
 		pu->parkingexten, 
 		pu->chan->name,
+		pu->parkinglot->name,
 		S_OR(pu->chan->cid.cid_num, "<unknown>"),
 		S_OR(pu->chan->cid.cid_name, "<unknown>")
 		);
 }
 
-/*! 
- * \brief Take care of parked calls and unpark them if needed 
- * \param ignore unused var.
- * 
- * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
- * if so, remove channel from parking lot and return it to the extension that parked it.
- * Check if parked channel decided to hangup, wait until next FD via select().
-*/
-static void *do_parking_thread(void *ignore)
+/*! \brief Run management on parkinglots, collad once per parkinglot */
+int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *ms, int *max)
 {
-	char parkingslot[AST_MAX_EXTENSION];
-	fd_set rfds, efds;	/* results from previous select, to be preserved across loops. */
 
-	FD_ZERO(&rfds);
-	FD_ZERO(&efds);
+	struct parkeduser *pu;
+	int res = 0;
+	char parkingslot[AST_MAX_EXTENSION];
 
-	for (;;) {
-		struct parkeduser *pu;
-		int ms = -1;	/* select timeout, uninitialized */
-		int max = -1;	/* max fd, none there yet */
-		fd_set nrfds, nefds;	/* args for the next select */
-		FD_ZERO(&nrfds);
-		FD_ZERO(&nefds);
-
-		AST_LIST_LOCK(&parkinglot);
-		AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
-			struct ast_channel *chan = pu->chan;	/* shorthand */
-			int tms;        /* timeout for this item */
-			int x;          /* fd index in channel */
-			struct ast_context *con;
-
-			if (pu->notquiteyet) /* Pretend this one isn't here yet */
-				continue;
-			tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
-			if (tms > pu->parkingtime) {
-				ast_indicate(chan, AST_CONTROL_UNHOLD);
-				/* Get chan, exten from derived kludge */
-				if (pu->peername[0]) {
-					char *peername = ast_strdupa(pu->peername);
-					char *cp = strrchr(peername, '-');
-					char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
-					int i;
-
-					if (cp) 
-						*cp = 0;
-					ast_copy_string(peername_flat,peername,sizeof(peername_flat));
-					for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
-						if (peername_flat[i] == '/') 
-							peername_flat[i]= '0';
-					}
-					con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
-					if (!con)
-						ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
-					if (con) {
-						char returnexten[AST_MAX_EXTENSION];
-						struct ast_datastore *features_datastore;
-						struct ast_dial_features *dialfeatures = NULL;
+	/* TODO: I believe this reference increase is not necessary since the iterator in the calling function already did so */
+	//parkinglot_addref(curlot);
+	/* Lock parking list */
+	AST_LIST_LOCK(&curlot->parkings);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&curlot->parkings, pu, list) {
+		struct ast_channel *chan = pu->chan;	/* shorthand */
+		int tms;        /* timeout for this item */
+		int x;          /* fd index in channel */
+		struct ast_context *con;
+
+		if (pu->notquiteyet) { /* Pretend this one isn't here yet */
+			continue;
+		}
+		tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
+		if (tms > pu->parkingtime) {
+			/* Stop music on hold */
+			ast_indicate(pu->chan, AST_CONTROL_UNHOLD);
+			/* Get chan, exten from derived kludge */
+			if (pu->peername[0]) {
+				char *peername = ast_strdupa(pu->peername);
+				char *cp = strrchr(peername, '-');
+				char peername_flat[AST_MAX_EXTENSION]; /* using something like Zap/52 for an extension name is NOT a good idea */
+				int i;
+
+				if (cp) 
+					*cp = 0;
+				ast_copy_string(peername_flat,peername,sizeof(peername_flat));
+				for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
+					if (peername_flat[i] == '/') 
+						peername_flat[i]= '0';
+				}
+				con = ast_context_find_or_create(NULL, NULL, pu->parkinglot->parking_con_dial, registrar);
+				if (!con) {
+					ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", pu->parkinglot->parking_con_dial);
+				}
+				if (con) {
+					char returnexten[AST_MAX_EXTENSION];
+					struct ast_datastore *features_datastore;
+					struct ast_dial_features *dialfeatures = NULL;
 
-						ast_channel_lock(chan);
+					ast_channel_lock(chan);
 
-						if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
-							dialfeatures = features_datastore->data;
+					if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
+						dialfeatures = features_datastore->data;
 
-						ast_channel_unlock(chan);
+					ast_channel_unlock(chan);
 
-						if (dialfeatures)
-							snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
-						else /* Existing default */
-							snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
+					if (dialfeatures)
+						snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
+					else /* Existing default */
+						snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
 
-						ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
-					}
-					if (comebacktoorigin) {
-						set_c_e_p(chan, parking_con_dial, peername_flat, 1);
-					} else {
-						ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
-						snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
-						pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
-						set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
-					}
+					ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
+				}
+				if (comebacktoorigin) {
+					set_c_e_p(chan, pu->parkinglot->parking_con_dial, peername_flat, 1);
 				} else {
-					/* They've been waiting too long, send them back to where they came.  Theoretically they
-					   should have their original extensions and such, but we copy to be on the safe side */
-					set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+					ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
+					snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
+					pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
+					set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
 				}
+			} else {
+				/* They've been waiting too long, send them back to where they came.  Theoretically they
+				   should have their original extensions and such, but we copy to be on the safe side */
+				set_c_e_p(chan, pu->context, pu->exten, pu->priority);
+			}
+			post_manager_event("ParkedCallTimeOut", pu);
+
+			ast_verb(2, "Timeout for %s parked on %d (%s). Returning to %s,%s,%d\n", pu->chan->name, pu->parkingnum, pu->parkinglot->name, pu->chan->context, pu->chan->exten, pu->chan->priority);
+			/* Start up the PBX, or hang them up */
+			if (ast_pbx_start(chan))  {
+				ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", pu->chan->name);
+				ast_hangup(chan);
+			}
+			/* And take them out of the parking lot */
+			con = ast_context_find(pu->parkinglot->parking_con);
+			if (con) {
+				if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
+					ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+				else
+					notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
+			} else
+				ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+			AST_LIST_REMOVE_CURRENT(list);
+			parkinglot_unref(curlot);
+		} else {	/* still within parking time, process descriptors */
+			for (x = 0; x < AST_MAX_FDS; x++) {
+				struct ast_frame *f;
 
-				post_manager_event("ParkedCallTimeOut", pu);
+				if ((chan->fds[x] == -1) && (!FD_ISSET(chan->fds[x], rfds) && !FD_ISSET(pu->chan->fds[x], efds))) 
+					continue;
+				
+				if (FD_ISSET(chan->fds[x], efds))
+					ast_set_flag(chan, AST_FLAG_EXCEPTION);
+				else
+					ast_clear_flag(chan, AST_FLAG_EXCEPTION);
+				chan->fdno = x;
+
+				/* See if they need servicing */
+				f = ast_read(pu->chan);
+				/* Hangup? */
+				if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass ==  AST_CONTROL_HANGUP))) {
+					if (f)
+						ast_frfree(f);
+					post_manager_event("ParkedCallGiveUp", pu);
 
-				ast_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
-				/* Start up the PBX, or hang them up */
-				if (ast_pbx_start(chan))  {
-					ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
+					/* There's a problem, hang them up*/
+					ast_verb(2, "%s got tired of being parked\n", chan->name);
 					ast_hangup(chan);
-				}
-				/* And take them out of the parking lot */
-				AST_LIST_REMOVE_CURRENT(list);
-				con = ast_context_find(parking_con);
-				if (con) {
-					if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
-						ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-					else
-						notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
-				} else
-					ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-				ast_free(pu);
-			} else {	/* still within parking time, process descriptors */
-				for (x = 0; x < AST_MAX_FDS; x++) {
-					struct ast_frame *f;
-
-					if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
-						continue;	/* nothing on this descriptor */
-
-					if (FD_ISSET(chan->fds[x], &efds))
-						ast_set_flag(chan, AST_FLAG_EXCEPTION);
-					else
-						ast_clear_flag(chan, AST_FLAG_EXCEPTION);
-					chan->fdno = x;
-
-					/* See if they need servicing */
-					f = ast_read(chan);
-					if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass ==  AST_CONTROL_HANGUP)) {
-						if (f)
-							ast_frfree(f);
-						post_manager_event("ParkedCallGiveUp", pu);
-
-						/* There's a problem, hang them up*/
-						ast_verb(2, "%s got tired of being parked\n", chan->name);
-						ast_hangup(chan);
-						/* And take them out of the parking lot */
-						AST_LIST_REMOVE_CURRENT(list);
-						con = ast_context_find(parking_con);
-						if (con) {
-							if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
-								ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
-							else
-								notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
-						} else
-							ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-						ast_free(pu);
-						break;
-					} else {
-						/*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
-						ast_frfree(f);
-						if (pu->moh_trys < 3 && !chan->generatordata) {
-							ast_debug(1, "MOH on parked call stopped by outside source.  Restarting.\n");
-							ast_indicate_data(chan, AST_CONTROL_HOLD, 
-								S_OR(parkmohclass, NULL),
-								!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
-							pu->moh_trys++;
-						}
-						goto std;	/*! \todo XXX Ick: jumping into an else statement??? XXX */
+					/* And take them out of the parking lot */
+					con = ast_context_find(curlot->parking_con);
+					if (con) {
+						if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
+							ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
+						else
+							notify_metermaids(pu->parkingexten, curlot->parking_con, AST_DEVICE_NOT_INUSE);
+					} else
+						ast_log(LOG_WARNING, "Whoa, no parking context for parking lot %s?\n", curlot->name);
+					AST_LIST_REMOVE_CURRENT(list);
+					parkinglot_unref(curlot);
+					break;
+				} else {
+					/* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
+					ast_frfree(f);
+					if (pu->moh_trys < 3 && !chan->generatordata) {
+						ast_debug(1, "MOH on parked call stopped by outside source.  Restarting on channel %s.\n", chan->name);
+						ast_indicate_data(chan, AST_CONTROL_HOLD, 
+							S_OR(curlot->mohclass, NULL),
+							(!ast_strlen_zero(curlot->mohclass) ? strlen(curlot->mohclass) + 1 : 0));
+						pu->moh_trys++;
 					}
-
-				} /* end for */
-				if (x >= AST_MAX_FDS) {
-std:					for (x=0; x<AST_MAX_FDS; x++) {	/* mark fds for next round */
-						if (chan->fds[x] > -1) {
-							FD_SET(chan->fds[x], &nrfds);
-							FD_SET(chan->fds[x], &nefds);
-							if (chan->fds[x] > max)
-								max = chan->fds[x];
-						}
+					goto std;	/* XXX Ick: jumping into an else statement??? XXX */
+				}
+			} /* End for */
+			if (x >= AST_MAX_FDS) {
+std:				for (x=0; x<AST_MAX_FDS; x++) {	/* mark fds for next round */
+					if (chan->fds[x] > -1) {
+						FD_SET(chan->fds[x], nrfds);
+						FD_SET(chan->fds[x], nefds);
+						if (chan->fds[x] > *max)
+							*max = chan->fds[x];
 					}
-					/* Keep track of our shortest wait */
-					if (tms < ms || ms < 0)
-						ms = tms;
 				}
+				/* Keep track of our shortest wait */
+				if (tms < *ms || *ms < 0)
+					*ms = tms;
 			}
-		} /* end while */
-		AST_LIST_TRAVERSE_SAFE_END
-		AST_LIST_UNLOCK(&parkinglot);
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END;
+	AST_LIST_UNLOCK(&curlot->parkings);
+	return res;
+}
+
+/*! 
+ * \brief Take care of parked calls and unpark them if needed 
+ * \param ignore unused var.
+ * 
+ * Start inf loop, lock parking lot, check if any parked channels have gone above timeout
+ * if so, remove channel from parking lot and return it to the extension that parked it.
+ * Check if parked channel decided to hangup, wait until next FD via select().
+*/
+static void *do_parking_thread(void *ignore)
+{
+	fd_set rfds, efds;	/* results from previous select, to be preserved across loops. */
+	fd_set nrfds, nefds;	/* args for the next select */
+	FD_ZERO(&nrfds);
+	FD_ZERO(&nefds);
+
+	for (;;) {
+		int res = 0;
+		int ms = -1;	/* select timeout, uninitialized */
+		int max = -1;	/* max fd, none there yet */
+		struct ao2_iterator iter;
+		struct ast_parkinglot *curlot;
+		iter = ao2_iterator_init(parkinglots, 0);
+
+		while ((curlot = ao2_iterator_next(&iter))) {
+			res = manage_parkinglot(curlot, &rfds, &efds, &nrfds, &nefds, &ms, &max);
+			ao2_ref(curlot, -1);
+		}
+
 		rfds = nrfds;
 		efds = nefds;
 		{
@@ -2357,6 +2450,25 @@ std:					for (x=0; x<AST_MAX_FDS; x++) {	/* mark fds for next round */
 	return NULL;	/* Never reached */
 }
 
+/*! \brief Find parkinglot by name */
+struct ast_parkinglot *find_parkinglot(const char *name)
+{
+	struct ast_parkinglot *parkinglot = NULL;
+	struct ast_parkinglot tmp_parkinglot;
+	
+	if (ast_strlen_zero(name))
+		return NULL;
+
+	ast_copy_string(tmp_parkinglot.name, name, sizeof(tmp_parkinglot.name));
+
+	parkinglot = ao2_find(parkinglots, &tmp_parkinglot, OBJ_POINTER);
+
+	if (parkinglot && option_debug)
+		ast_log(LOG_DEBUG, "Found Parkinglot: %s\n", parkinglot->name);
+
+	return parkinglot;
+}
+
 /*! \brief Park a call */
 static int park_call_exec(struct ast_channel *chan, void *data)
 {
@@ -2367,12 +2479,25 @@ static int park_call_exec(struct ast_channel *chan, void *data)
 	char orig_exten[AST_MAX_EXTENSION];
 	int orig_priority = chan->priority;
 
+	const char *parkinglotname = DEFAULT_PARKINGLOT;
+	struct ast_parkinglot *parkinglot = NULL;
+ 
 	/* Data is unused at the moment but could contain a parking
 	   lot context eventually */
 	int res = 0;
 
 	ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
 
+	/* Check if the channel has a parking lot */
+	parkinglotname = findparkinglotname(chan);
+
+	if (parkinglotname) {
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
+		parkinglot = find_parkinglot(parkinglotname);	
+	}
+
+
 	/* Setup the exten/priority to be s/1 since we don't know
 	   where this call should return */
 	strcpy(chan->exten, "s");
@@ -2385,7 +2510,7 @@ static int park_call_exec(struct ast_channel *chan, void *data)
 		res = ast_safe_sleep(chan, 1000);
 	/* Park the call */
 	if (!res) {
-		res = park_call_full(chan, chan, 0, NULL, orig_chan_name);
+		res = park_call_full(chan, chan, 0, NULL, orig_chan_name, parkinglot);
 		/* Continue on in the dialplan */
 		if (res == 1) {
 			ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
@@ -2399,7 +2524,7 @@ static int park_call_exec(struct ast_channel *chan, void *data)
 }
 
 /*! \brief Pickup parked call */
-static int park_exec(struct ast_channel *chan, void *data)
+static int park_exec_full(struct ast_channel *chan, void *data, struct ast_parkinglot *parkinglot)
 {
 	int res = 0;
 	struct ast_channel *peer=NULL;
@@ -2411,24 +2536,28 @@ static int park_exec(struct ast_channel *chan, void *data)
 	if (data)
 		park = atoi((char *)data);
 
-	AST_LIST_LOCK(&parkinglot);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
+	parkinglot = find_parkinglot(findparkinglotname(chan)); 	
+	if (!parkinglot)
+		parkinglot = default_parkinglot;
+
+	AST_LIST_LOCK(&parkinglot->parkings);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot->parkings, pu, list) {
 		if (!data || pu->parkingnum == park) {
 			AST_LIST_REMOVE_CURRENT(list);
 			break;
 		}
 	}
 	AST_LIST_TRAVERSE_SAFE_END
-	AST_LIST_UNLOCK(&parkinglot);
+	AST_LIST_UNLOCK(&parkinglot->parkings);
 
 	if (pu) {
 		peer = pu->chan;
-		con = ast_context_find(parking_con);
+		con = ast_context_find(parkinglot->parking_con);
 		if (con) {
 			if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL))
 				ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
 			else
-				notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
+				notify_metermaids(pu->parkingexten, parkinglot->parking_con, AST_DEVICE_NOT_INUSE);
 		} else
 			ast_log(LOG_WARNING, "Whoa, no parking context?\n");
 
@@ -2449,6 +2578,10 @@ static int park_exec(struct ast_channel *chan, void *data)
 	if (chan->_state != AST_STATE_UP)
 		ast_answer(chan);
 
+	//XXX Why do we unlock here ?
+	// uncomment it for now, till my setup with debug_threads and detect_deadlocks starts to complain
+	//ASTOBJ_UNLOCK(parkinglot);
+
 	if (peer) {
 		/* Play a courtesy to the source(s) configured to prefix the bridge connecting */
 		
@@ -2491,13 +2624,13 @@ static int park_exec(struct ast_channel *chan, void *data)
 		pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
 		ast_cdr_setdestchan(chan->cdr, peer->name);
 		memset(&config, 0, sizeof(struct ast_bridge_config));
-		if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
+		if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
 			ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
-		if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
+		if ((parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH))
 			ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
-		if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
+		if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
 			ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
-		if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
+		if ((parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkinglot->parkedcallreparking == AST_FEATURE_FLAG_BYBOTH))
 			ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
 		res = ast_bridge_call(chan, peer, &config);
 
@@ -2519,6 +2652,154 @@ static int park_exec(struct ast_channel *chan, void *data)
 	return res;
 }
 
+static int park_exec(struct ast_channel *chan, void *data) 
+{
+	return park_exec_full(chan, data, default_parkinglot);
+}
+
+/*! \brief Unreference parkinglot object. If no more references,
+	then go ahead and delete it */
+static void parkinglot_unref(struct ast_parkinglot *parkinglot) 
+{
+	int refcount = ao2_ref(parkinglot, -1);
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount - 1);
+}
+
+static struct ast_parkinglot *parkinglot_addref(struct ast_parkinglot *parkinglot)
+{
+	int refcount = ao2_ref(parkinglot, +1);
+	if (option_debug > 2)
+		ast_log(LOG_DEBUG, "Multiparking: %s refcount now %d\n", parkinglot->name, refcount + 1);
+	return parkinglot;
+}
+
+/*! \brief Allocate parking lot structure */
+static struct ast_parkinglot *create_parkinglot(char *name)
+{
+	struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
+
+	if (!name)
+		return NULL;
+
+	newlot = ao2_alloc(sizeof(*newlot), parkinglot_destroy);
+	if (!newlot)
+		return NULL;
+	
+	ast_copy_string(newlot->name, name, sizeof(newlot->name));
+
+	return newlot;
+}
+
+/*! \brief Destroy a parking lot */
+static void parkinglot_destroy(void *obj)
+{
+	struct ast_parkinglot *ruin = obj;
+	struct ast_context *con;
+	con = ast_context_find(ruin->parking_con);
+	if (con)
+		ast_context_destroy(con, registrar);
+	ao2_unlink(parkinglots, ruin);
+}
+
+/*! \brief Build parkinglot from configuration and chain it in */
+static struct ast_parkinglot *build_parkinglot(char *name, struct ast_variable *var)
+{
+	struct ast_parkinglot *parkinglot;
+	struct ast_context *con = NULL;
+
+	struct ast_variable *confvar = var;
+	int error = 0;
+	int start = 0, end = 0;
+	int oldparkinglot = 0;
+
+	parkinglot = find_parkinglot(name);
+	if (parkinglot)
+		oldparkinglot = 1;
+	else
+		parkinglot = create_parkinglot(name);
+
+	if (!parkinglot)
+		return NULL;
+
+	ao2_lock(parkinglot);
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
+	
+	/* Do some config stuff */
+	while(confvar) {
+		if (!strcasecmp(confvar->name, "context")) {
+			ast_copy_string(parkinglot->parking_con, confvar->value, sizeof(parkinglot->parking_con));
+		} else if (!strcasecmp(confvar->name, "parkingtime")) {
+			if ((sscanf(confvar->value, "%d", &parkinglot->parkingtime) != 1) || (parkinglot->parkingtime < 1)) {
+				ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", confvar->value);
+				parkinglot->parkingtime = DEFAULT_PARK_TIME;
+			} else
+				parkinglot->parkingtime = parkinglot->parkingtime * 1000;
+		} else if (!strcasecmp(confvar->name, "parkpos")) {
+			if (sscanf(confvar->value, "%d-%d", &start, &end) != 2) {
+				ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of parking.conf\n", confvar->lineno);
+				error = 1;
+			} else {
+				parkinglot->parking_start = start;
+				parkinglot->parking_stop = end;
+			}
+		} else if (!strcasecmp(confvar->name, "findslot")) {
+			parkinglot->parkfindnext = (!strcasecmp(confvar->value, "next"));
+		}
+		confvar = confvar->next;
+	}
+	/* make sure parkingtime is set if not specified */
+	if (parkinglot->parkingtime == 0) {
+		parkinglot->parkingtime = DEFAULT_PARK_TIME;
+	}
+
+	if (!var) {	/* Default parking lot */
+		ast_copy_string(parkinglot->parking_con, "parkedcalls", sizeof(parkinglot->parking_con));
+		ast_copy_string(parkinglot->parking_con_dial, "park-dial", sizeof(parkinglot->parking_con_dial));
+		ast_copy_string(parkinglot->mohclass, "default", sizeof(parkinglot->mohclass));
+	}
+
+	/* Check for errors */
+	if (ast_strlen_zero(parkinglot->parking_con)) {
+		ast_log(LOG_WARNING, "Parking lot %s lacks context\n", name);
+		error = 1;
+	}
+
+	/* Create context */
+	if (!error && !(con = ast_context_find_or_create(NULL, NULL, parkinglot->parking_con, registrar))) {
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parkinglot->parking_con);
+		error = 1;
+	}
+
+	/* Add a parking extension into the context */
+	if (!oldparkinglot) {
+		if (ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, strdup(""), ast_free, registrar) == -1)
+			error = 1;
+	}
+
+	ao2_unlock(parkinglot);
+
+	if (error) {
+		ast_log(LOG_WARNING, "Parking %s not open for business. Configuration error.\n", name);
+		parkinglot_destroy(parkinglot);
+		return NULL;
+	}
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Parking %s now open for business. (start exten %d end %d)\n", name, start, end);
+
+
+	/* Move it into the list, if it wasn't already there */
+	if (!oldparkinglot) {
+		ao2_link(parkinglots, parkinglot);
+	}
+	parkinglot_unref(parkinglot);
+
+	return parkinglot;
+}
+
+
 /*! 
  * \brief Add parking hints for all defined parking lots 
  * \param context
@@ -2560,28 +2841,42 @@ static int load_config(void)
 		"applicationmap"
 	};
 
-	if (!ast_strlen_zero(parking_con)) {
+	if (default_parkinglot) {
+		strcpy(old_parking_con, default_parkinglot->parking_con);
 		strcpy(old_parking_ext, parking_ext);
-		strcpy(old_parking_con, parking_con);
-	} 
+	} else {
+		default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
+		if (default_parkinglot) {
+			ao2_lock(default_parkinglot);
+			default_parkinglot->parking_start = 701;
+			default_parkinglot->parking_stop = 750;
+			default_parkinglot->parking_offset = 0;
+			default_parkinglot->parkfindnext = 0;
+			default_parkinglot->parkingtime = 0;
+			ao2_unlock(default_parkinglot);
+		}
+	}
+	if (default_parkinglot) {
+		if (option_debug)
+			ast_log(LOG_DEBUG, "Configuration of default parkinglot done.\n");
+	} else {
+		ast_log(LOG_ERROR, "Configuration of default parkinglot failed.\n");
+		return -1;
+	}
+	
 
 	/* Reset to defaults */
-	strcpy(parking_con, "parkedcalls");
-	strcpy(parking_con_dial, "park-dial");
 	strcpy(parking_ext, "700");
 	strcpy(pickup_ext, "*8");
-	strcpy(parkmohclass, "default");
 	courtesytone[0] = '\0';
 	strcpy(xfersound, "beep");
 	strcpy(xferfailsound, "pbx-invalid");
-	parking_start = 701;
-	parking_stop = 750;
-	parkfindnext = 0;
 	adsipark = 0;
 	comebacktoorigin = 1;
-	parkaddhints = 0;
-	parkedcalltransfers = 0;
-	parkedcallreparking = 0;
+
+	default_parkinglot->parkaddhints = 0;
+	default_parkinglot->parkedcalltransfers = 0;
+	default_parkinglot->parkedcallreparking = 0;
 
 	transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
 	featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
@@ -2599,38 +2894,40 @@ static int load_config(void)
 		if (!strcasecmp(var->name, "parkext")) {
 			ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
 		} else if (!strcasecmp(var->name, "context")) {
-			ast_copy_string(parking_con, var->value, sizeof(parking_con));
+			ast_copy_string(default_parkinglot->parking_con, var->value, sizeof(default_parkinglot->parking_con));
 		} else if (!strcasecmp(var->name, "parkingtime")) {
-			if ((sscanf(var->value, "%d", &parkingtime) != 1) || (parkingtime < 1)) {
+			if ((sscanf(var->value, "%d", &default_parkinglot->parkingtime) != 1) || (default_parkinglot->parkingtime < 1)) {
 				ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
-				parkingtime = DEFAULT_PARK_TIME;
+				default_parkinglot->parkingtime = DEFAULT_PARK_TIME;
 			} else
-				parkingtime = parkingtime * 1000;
+				default_parkinglot->parkingtime = default_parkinglot->parkingtime * 1000;
 		} else if (!strcasecmp(var->name, "parkpos")) {
 			if (sscanf(var->value, "%d-%d", &start, &end) != 2) {
 				ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
+			} else if (default_parkinglot) {
+				default_parkinglot->parking_start = start;
+				default_parkinglot->parking_stop = end;
 			} else {
-				parking_start = start;
-				parking_stop = end;
+				ast_log(LOG_WARNING, "No default parking lot!\n");
 			}
 		} else if (!strcasecmp(var->name, "findslot")) {
-			parkfindnext = (!strcasecmp(var->value, "next"));
+			default_parkinglot->parkfindnext = (!strcasecmp(var->value, "next"));
 		} else if (!strcasecmp(var->name, "parkinghints")) {
-			parkaddhints = ast_true(var->value);
+			default_parkinglot->parkaddhints = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "parkedcalltransfers")) {
 			if (!strcasecmp(var->value, "both"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
+				default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
 			else if (!strcasecmp(var->value, "caller"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
+				default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
 			else if (!strcasecmp(var->value, "callee"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
+				default_parkinglot->parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
 		} else if (!strcasecmp(var->name, "parkedcallreparking")) {
 			if (!strcasecmp(var->value, "both"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
+				default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYBOTH;
 			else if (!strcasecmp(var->value, "caller"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
+				default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLER;
 			else if (!strcasecmp(var->value, "callee"))
-				parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
+				default_parkinglot->parkedcallreparking = AST_FEATURE_FLAG_BYCALLEE;
 		} else if (!strcasecmp(var->name, "adsipark")) {
 			adsipark = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "transferdigittimeout")) {
@@ -2681,7 +2978,7 @@ static int load_config(void)
 		} else if (!strcasecmp(var->name, "comebacktoorigin")) {
 			comebacktoorigin = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "parkedmusicclass")) {
-			ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
+			ast_copy_string(default_parkinglot->mohclass, var->value, sizeof(default_parkinglot->mohclass));
 		}
 	}
 
@@ -2777,6 +3074,16 @@ static int load_config(void)
 
 	ctg = NULL;
 	while ((ctg = ast_category_browse(cfg, ctg))) {
+		/* Is this a parkinglot definition ? */
+		if (!strncasecmp(ctg, "parkinglot_", strlen("parkinglot_"))) {
+			ast_debug(2, "Found configuration section %s, assume parking context\n", ctg);
+			if(!build_parkinglot(ctg, ast_variable_browse(cfg, ctg)))
+				ast_log(LOG_ERROR, "Could not build parking lot %s. Configuration error.\n", ctg);
+			else
+				ast_debug(1, "Configured parking context %s\n", ctg);
+			continue;	
+		}
+		/* No, check if it's a group */
 		for (i = 0; i < ARRAY_LEN(categories); i++) {
 			if (!strcasecmp(categories[i], ctg))
 				break;
@@ -2815,15 +3122,15 @@ static int load_config(void)
 		ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
 	}
 	
-	if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
-		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
+	if (!(con = ast_context_find_or_create(NULL, NULL, default_parkinglot->parking_con, registrar))) {
+		ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", default_parkinglot->parking_con);
 		return -1;
 	}
 	res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
-	if (parkaddhints)
-		park_add_hints(parking_con, parking_start, parking_stop);
+	if (default_parkinglot->parkaddhints)
+		park_add_hints(default_parkinglot->parking_con, default_parkinglot->parking_start, default_parkinglot->parking_stop);
 	if (!res)
-		notify_metermaids(ast_parking_ext(), parking_con, AST_DEVICE_INUSE);
+		notify_metermaids(ast_parking_ext(), default_parkinglot->parking_con, AST_DEVICE_INUSE);
 	return res;
 
 }
@@ -2841,6 +3148,8 @@ static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cl
 {
 	int i;
 	struct ast_call_feature *feature;
+	struct ao2_iterator iter;
+	struct ast_parkinglot *curlot;
 #define HFS_FORMAT "%-25s %-7s %-7s\n"
 
 	switch (cmd) {
@@ -2876,21 +3185,36 @@ static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cl
 			ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
 		AST_LIST_UNLOCK(&feature_list);
 	}
-	ast_cli(a->fd, "\nCall parking\n");
-	ast_cli(a->fd, "------------\n");
-	ast_cli(a->fd,"%-20s:      %s\n", "Parking extension", parking_ext);
-	ast_cli(a->fd,"%-20s:      %s\n", "Parking context", parking_con);
-	ast_cli(a->fd,"%-20s:      %d-%d\n", "Parked call extensions", parking_start, parking_stop);
-	ast_cli(a->fd,"\n");
+
+	// loop through all the parking lots
+	iter = ao2_iterator_init(parkinglots, 0);
+
+	while ((curlot = ao2_iterator_next(&iter))) {
+		ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);
+		ast_cli(a->fd, "------------\n");
+		ast_cli(a->fd,"%-22s:      %s\n", "Parking extension", parking_ext);
+		ast_cli(a->fd,"%-22s:      %s\n", "Parking context", curlot->parking_con);
+		ast_cli(a->fd,"%-22s:      %d-%d\n", "Parked call extensions", curlot->parking_start, curlot->parking_stop);
+		ast_cli(a->fd,"\n");
+		ao2_ref(curlot, -1);
+	}
+
 
 	return CLI_SUCCESS;
 }
 
 int ast_features_reload(void)
 {
-	load_config();
+	int res;
+	/* Release parking lot list */
+	//ASTOBJ_CONTAINER_MARKALL(&parkinglots);
+	// TODO: I don't think any marking is necessary
 
-	return RESULT_SUCCESS;
+	/* Reload configuration */
+	res = load_config();
+	
+	//ASTOBJ_CONTAINER_PRUNE_MARKED(&parkinglots, parkinglot_destroy);
+	return res;
 }
 
 static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2905,7 +3229,7 @@ static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast
 	case CLI_GENERATE:
 		return NULL;
 	}
-	load_config();
+	ast_features_reload();
 
 	return CLI_SUCCESS;
 }
@@ -3066,6 +3390,8 @@ static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli
 {
 	struct parkeduser *cur;
 	int numparked = 0;
+	struct ao2_iterator iter;
+	struct ast_parkinglot *curlot;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -3084,17 +3410,27 @@ static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli
 	ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
 		, "Context", "Extension", "Pri", "Timeout");
 
-	AST_LIST_LOCK(&parkinglot);
-	AST_LIST_TRAVERSE(&parkinglot, cur, list) {
-		ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
-			,cur->parkingexten, cur->chan->name, cur->context, cur->exten
-			,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
+	iter = ao2_iterator_init(parkinglots, 0);
+	while ((curlot = ao2_iterator_next(&iter))) {
+		int lotparked = 0;
+		ast_cli(a->fd, "*** Parking lot: %s\n", curlot->name);
+
+		AST_LIST_LOCK(&curlot->parkings);
+		AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
+			ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
+				,cur->parkingexten, cur->chan->name, cur->context, cur->exten
+				,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
+			numparked++;
+			numparked += lotparked;
+		}
+		AST_LIST_UNLOCK(&curlot->parkings);
+		if (lotparked)
+			ast_cli(a->fd, "   %d parked call%s in parking lot %s\n", lotparked, ESS(lotparked), curlot->name);
 
-		numparked++;
+		ao2_ref(curlot, -1);
 	}
-	AST_LIST_UNLOCK(&parkinglot);
-	ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
 
+	ast_cli(a->fd, "---\n%d parked call%s in total.\n", numparked, ESS(numparked));
 
 	return CLI_SUCCESS;
 }
@@ -3128,29 +3464,36 @@ static int manager_parking_status(struct mansession *s, const struct message *m)
 	struct parkeduser *cur;
 	const char *id = astman_get_header(m, "ActionID");
 	char idText[256] = "";
+	struct ao2_iterator iter;
+	struct ast_parkinglot *curlot;
 
 	if (!ast_strlen_zero(id))
 		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 
 	astman_send_ack(s, m, "Parked calls will follow");
 
-	AST_LIST_LOCK(&parkinglot);
-
-	AST_LIST_TRAVERSE(&parkinglot, cur, list) {
-		astman_append(s, "Event: ParkedCall\r\n"
-			"Exten: %d\r\n"
-			"Channel: %s\r\n"
-			"From: %s\r\n"
-			"Timeout: %ld\r\n"
-			"CallerIDNum: %s\r\n"
-			"CallerIDName: %s\r\n"
-			"%s"
-			"\r\n",
-			cur->parkingnum, cur->chan->name, cur->peername,
-			(long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
-			S_OR(cur->chan->cid.cid_num, ""),	/* XXX in other places it is <unknown> */
-			S_OR(cur->chan->cid.cid_name, ""),
-			idText);
+	iter = ao2_iterator_init(parkinglots, 0);
+	while ((curlot = ao2_iterator_next(&iter))) {
+
+		AST_LIST_LOCK(&curlot->parkings);
+		AST_LIST_TRAVERSE(&curlot->parkings, cur, list) {
+			astman_append(s, "Event: ParkedCall\r\n"
+				"Exten: %d\r\n"
+				"Channel: %s\r\n"
+				"From: %s\r\n"
+				"Timeout: %ld\r\n"
+				"CallerIDNum: %s\r\n"
+				"CallerIDName: %s\r\n"
+				"%s"
+				"\r\n",
+				cur->parkingnum, cur->chan->name, cur->peername,
+				(long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
+				S_OR(cur->chan->cid.cid_num, ""),	/* XXX in other places it is <unknown> */
+				S_OR(cur->chan->cid.cid_name, ""),
+				idText);
+		}
+		AST_LIST_UNLOCK(&curlot->parkings);
+		ao2_ref(curlot, -1);
 	}
 
 	astman_append(s,
@@ -3158,7 +3501,6 @@ static int manager_parking_status(struct mansession *s, const struct message *m)
 		"%s"
 		"\r\n",idText);
 
-	AST_LIST_UNLOCK(&parkinglot);
 
 	return RESULT_SUCCESS;
 }
@@ -3427,8 +3769,7 @@ int ast_features_init(void)
 
 	ast_register_application2(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip, NULL);
 
-	memset(parking_ext, 0, sizeof(parking_ext));
-	memset(parking_con, 0, sizeof(parking_con));
+	parkinglots = ao2_container_alloc(7, parkinglot_hash_cb, parkinglot_cmp_cb);
 
 	if ((res = load_config()))
 		return res;
@@ -3439,8 +3780,7 @@ int ast_features_init(void)
 		res = ast_register_application2(parkcall, park_call_exec, synopsis2, descrip2, NULL);
 	if (!res) {
 		ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
-		ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
-			"Park a channel", mandescr_park); 
+		ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park, "Park a channel", mandescr_park); 
 		ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
 	}