Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision 4c6fd56b8079778d8d40e0d5ffc6a1e8e8ad2b5b)
+++ uspace/lib/c/generic/loc.c	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -39,8 +39,5 @@
 #include <stdbool.h>
 
-static FIBRIL_MUTEX_INITIALIZE(loc_supp_block_mutex);
 static FIBRIL_MUTEX_INITIALIZE(loc_cons_block_mutex);
-
-static FIBRIL_MUTEX_INITIALIZE(loc_supplier_mutex);
 static FIBRIL_MUTEX_INITIALIZE(loc_consumer_mutex);
 
@@ -50,8 +47,5 @@
 static void *cat_change_arg = NULL;
 
-static async_sess_t *loc_supp_block_sess = NULL;
 static async_sess_t *loc_cons_block_sess = NULL;
-
-static async_sess_t *loc_supplier_sess = NULL;
 static async_sess_t *loc_consumer_sess = NULL;
 
@@ -108,5 +102,5 @@
 	if (!loc_callback_created) {
 		async_exch_t *exch =
-		    loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		    loc_exchange_begin_blocking();
 
 		ipc_call_t answer;
@@ -135,96 +129,49 @@
 /** Start an async exchange on the loc session (blocking).
  *
- * @param iface Location service interface to choose
- *
  * @return New exchange.
  *
  */
-async_exch_t *loc_exchange_begin_blocking(iface_t iface)
-{
-	switch (iface) {
-	case INTERFACE_LOC_SUPPLIER:
-		fibril_mutex_lock(&loc_supp_block_mutex);
-
-		while (loc_supp_block_sess == NULL) {
-			clone_session(&loc_supplier_mutex, loc_supplier_sess,
-			    &loc_supp_block_sess);
-
-			if (loc_supp_block_sess == NULL)
-				loc_supp_block_sess =
-				    service_connect_blocking(SERVICE_LOC,
-				    INTERFACE_LOC_SUPPLIER, 0, NULL);
-		}
-
-		fibril_mutex_unlock(&loc_supp_block_mutex);
-
-		clone_session(&loc_supplier_mutex, loc_supp_block_sess,
-		    &loc_supplier_sess);
-
-		return async_exchange_begin(loc_supp_block_sess);
-	case INTERFACE_LOC_CONSUMER:
-		fibril_mutex_lock(&loc_cons_block_mutex);
-
-		while (loc_cons_block_sess == NULL) {
-			clone_session(&loc_consumer_mutex, loc_consumer_sess,
-			    &loc_cons_block_sess);
-
-			if (loc_cons_block_sess == NULL)
-				loc_cons_block_sess =
-				    service_connect_blocking(SERVICE_LOC,
-				    INTERFACE_LOC_CONSUMER, 0, NULL);
-		}
-
-		fibril_mutex_unlock(&loc_cons_block_mutex);
-
-		clone_session(&loc_consumer_mutex, loc_cons_block_sess,
-		    &loc_consumer_sess);
-
-		return async_exchange_begin(loc_cons_block_sess);
-	default:
+async_exch_t *loc_exchange_begin_blocking(void)
+{
+	fibril_mutex_lock(&loc_cons_block_mutex);
+
+	while (loc_cons_block_sess == NULL) {
+		clone_session(&loc_consumer_mutex, loc_consumer_sess,
+		    &loc_cons_block_sess);
+
+		if (loc_cons_block_sess == NULL)
+			loc_cons_block_sess =
+			    service_connect_blocking(SERVICE_LOC,
+			    INTERFACE_LOC_CONSUMER, 0, NULL);
+	}
+
+	fibril_mutex_unlock(&loc_cons_block_mutex);
+
+	clone_session(&loc_consumer_mutex, loc_cons_block_sess,
+	    &loc_consumer_sess);
+
+	return async_exchange_begin(loc_cons_block_sess);
+}
+
+/** Start an async exchange on the loc session.
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *loc_exchange_begin(void)
+{
+	fibril_mutex_lock(&loc_consumer_mutex);
+
+	if (loc_consumer_sess == NULL)
+		loc_consumer_sess =
+		    service_connect(SERVICE_LOC,
+		    INTERFACE_LOC_CONSUMER, 0, NULL);
+
+	fibril_mutex_unlock(&loc_consumer_mutex);
+
+	if (loc_consumer_sess == NULL)
 		return NULL;
-	}
-}
-
-/** Start an async exchange on the loc session.
- *
- * @param iface Location service interface to choose
- *
- * @return New exchange.
- *
- */
-async_exch_t *loc_exchange_begin(iface_t iface)
-{
-	switch (iface) {
-	case INTERFACE_LOC_SUPPLIER:
-		fibril_mutex_lock(&loc_supplier_mutex);
-
-		if (loc_supplier_sess == NULL)
-			loc_supplier_sess =
-			    service_connect(SERVICE_LOC,
-			    INTERFACE_LOC_SUPPLIER, 0, NULL);
-
-		fibril_mutex_unlock(&loc_supplier_mutex);
-
-		if (loc_supplier_sess == NULL)
-			return NULL;
-
-		return async_exchange_begin(loc_supplier_sess);
-	case INTERFACE_LOC_CONSUMER:
-		fibril_mutex_lock(&loc_consumer_mutex);
-
-		if (loc_consumer_sess == NULL)
-			loc_consumer_sess =
-			    service_connect(SERVICE_LOC,
-			    INTERFACE_LOC_CONSUMER, 0, NULL);
-
-		fibril_mutex_unlock(&loc_consumer_mutex);
-
-		if (loc_consumer_sess == NULL)
-			return NULL;
-
-		return async_exchange_begin(loc_consumer_sess);
-	default:
-		return NULL;
-	}
+
+	return async_exchange_begin(loc_consumer_sess);
 }
 
@@ -240,7 +187,4 @@
 
 /** Register new server with loc.
- *
- * XXX Proper impementation - currently cannot actually call
- * this function more than once.
  *
  * @param name Server name
@@ -257,5 +201,12 @@
 		return ENOMEM;
 
-	exch = loc_exchange_begin_blocking(INTERFACE_LOC_SUPPLIER);
+	srv->sess = service_connect_blocking(SERVICE_LOC,
+	    INTERFACE_LOC_SUPPLIER, 0, NULL);
+	if (srv->sess == NULL) {
+		free(srv);
+		return ENOMEM;
+	}
+
+	exch = async_exchange_begin(srv->sess);
 
 	ipc_call_t answer;
@@ -265,5 +216,6 @@
 	if (retval != EOK) {
 		async_forget(req);
-		loc_exchange_end(exch);
+		async_exchange_end(exch);
+		async_hangup(srv->sess);
 		free(srv);
 		return retval;
@@ -278,7 +230,8 @@
 	 */
 	async_wait_for(req, &retval);
-	loc_exchange_end(exch);
-
-	if (retval != EOK) {
+	async_exchange_end(exch);
+
+	if (retval != EOK) {
+		async_hangup(srv->sess);
 		free(srv);
 		return retval;
@@ -293,10 +246,9 @@
  * Unregister server and free server object.
  *
- * XXX Proper implementation
- *
  * @param srv Server object
  */
 void loc_server_unregister(loc_srv_t *srv)
 {
+	async_hangup(srv->sess);
 	free(srv);
 }
@@ -312,8 +264,5 @@
     service_id_t *sid)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_SUPPLIER);
-
-	(void)srv;
-
+	async_exch_t *exch = async_exchange_begin(srv->sess);
 	ipc_call_t answer;
 	aid_t req = async_send_0(exch, LOC_SERVICE_REGISTER, &answer);
@@ -322,5 +271,5 @@
 	if (retval != EOK) {
 		async_forget(req);
-		loc_exchange_end(exch);
+		async_exchange_end(exch);
 		return retval;
 	}
@@ -332,5 +281,5 @@
 	 */
 	async_wait_for(req, &retval);
-	loc_exchange_end(exch);
+	async_exchange_end(exch);
 
 	if (retval != EOK) {
@@ -357,9 +306,7 @@
 	errno_t retval;
 
-	(void)srv;
-
-	exch = loc_exchange_begin_blocking(INTERFACE_LOC_SUPPLIER);
+	exch = async_exchange_begin(srv->sess);
 	retval = async_req_1_0(exch, LOC_SERVICE_UNREGISTER, sid);
-	loc_exchange_end(exch);
+	async_exchange_end(exch);
 
 	return (errno_t)retval;
@@ -372,7 +319,7 @@
 
 	if (flags & IPC_FLAG_BLOCKING)
-		exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin_blocking();
 	else {
-		exch = loc_exchange_begin(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin();
 		if (exch == NULL)
 			return errno;
@@ -425,5 +372,5 @@
 
 	*name = NULL;
-	exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	exch = loc_exchange_begin_blocking();
 
 	ipc_call_t answer;
@@ -505,7 +452,7 @@
 
 	if (flags & IPC_FLAG_BLOCKING)
-		exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin_blocking();
 	else {
-		exch = loc_exchange_begin(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin();
 		if (exch == NULL)
 			return errno;
@@ -554,7 +501,7 @@
 
 	if (flags & IPC_FLAG_BLOCKING)
-		exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin_blocking();
 	else {
-		exch = loc_exchange_begin(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin();
 		if (exch == NULL)
 			return errno;
@@ -590,5 +537,5 @@
 loc_object_type_t loc_id_probe(service_id_t handle)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 
 	sysarg_t type;
@@ -621,5 +568,5 @@
 int loc_null_create(void)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 
 	sysarg_t null_id;
@@ -636,5 +583,5 @@
 void loc_null_destroy(int null_id)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 	async_req_1_0(exch, LOC_NULL_DESTROY, (sysarg_t) null_id);
 	loc_exchange_end(exch);
@@ -665,7 +612,7 @@
 	errno_t retval;
 
-	exch = loc_exchange_begin_blocking(INTERFACE_LOC_SUPPLIER);
+	exch = async_exchange_begin(srv->sess);
 	retval = async_req_2_0(exch, LOC_SERVICE_ADD_TO_CAT, svc_id, cat_id);
-	loc_exchange_end(exch);
+	async_exchange_end(exch);
 
 	return retval;
@@ -686,5 +633,5 @@
 size_t loc_count_namespaces(void)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 	size_t size = loc_count_namespaces_internal(exch);
 	loc_exchange_end(exch);
@@ -695,5 +642,5 @@
 size_t loc_count_services(service_id_t ns_handle)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 	size_t size = loc_count_services_internal(exch, ns_handle);
 	loc_exchange_end(exch);
@@ -706,5 +653,5 @@
 	/* Loop until read is succesful */
 	while (true) {
-		async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		async_exch_t *exch = loc_exchange_begin_blocking();
 		size_t count = loc_count_namespaces_internal(exch);
 		loc_exchange_end(exch);
@@ -717,5 +664,5 @@
 			return 0;
 
-		exch = loc_exchange_begin(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin();
 
 		ipc_call_t answer;
@@ -755,5 +702,5 @@
 	/* Loop until read is succesful */
 	while (true) {
-		async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+		async_exch_t *exch = loc_exchange_begin_blocking();
 		size_t count = loc_count_services_internal(exch, ns_handle);
 		loc_exchange_end(exch);
@@ -766,5 +713,5 @@
 			return 0;
 
-		exch = loc_exchange_begin(INTERFACE_LOC_CONSUMER);
+		exch = loc_exchange_begin();
 
 		ipc_call_t answer;
@@ -803,5 +750,5 @@
     sysarg_t *id_buf, size_t buf_size, size_t *act_size)
 {
-	async_exch_t *exch = loc_exchange_begin_blocking(INTERFACE_LOC_CONSUMER);
+	async_exch_t *exch = loc_exchange_begin_blocking();
 
 	ipc_call_t answer;
Index: uspace/lib/c/include/loc.h
===================================================================
--- uspace/lib/c/include/loc.h	(revision 4c6fd56b8079778d8d40e0d5ffc6a1e8e8ad2b5b)
+++ uspace/lib/c/include/loc.h	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -43,6 +43,6 @@
 typedef void (*loc_cat_change_cb_t)(void *);
 
-extern async_exch_t *loc_exchange_begin_blocking(iface_t);
-extern async_exch_t *loc_exchange_begin(iface_t);
+extern async_exch_t *loc_exchange_begin_blocking(void);
+extern async_exch_t *loc_exchange_begin(void);
 extern void loc_exchange_end(async_exch_t *);
 
Index: uspace/lib/c/include/types/loc.h
===================================================================
--- uspace/lib/c/include/types/loc.h	(revision 4c6fd56b8079778d8d40e0d5ffc6a1e8e8ad2b5b)
+++ uspace/lib/c/include/types/loc.h	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -36,7 +36,9 @@
 #define _LIBC_TYPES_LOC_H_
 
+#include <async.h>
+
 /** Server register with location service */
 typedef struct {
-	int dummy;
+	async_sess_t *sess;
 } loc_srv_t;
 
Index: uspace/lib/c/meson.build
===================================================================
--- uspace/lib/c/meson.build	(revision 4c6fd56b8079778d8d40e0d5ffc6a1e8e8ad2b5b)
+++ uspace/lib/c/meson.build	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -1,3 +1,4 @@
 #
+# Copyright (c) 2023 Jiri Svoboda
 # Copyright (c) 2005 Martin Decky
 # Copyright (c) 2007 Jakub Jermar
@@ -186,4 +187,5 @@
 	'test/inttypes.c',
 	'test/io/table.c',
+	'test/loc.c',
 	'test/main.c',
 	'test/mem.c',
Index: uspace/lib/c/test/loc.c
===================================================================
--- uspace/lib/c/test/loc.c	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
+++ uspace/lib/c/test/loc.c	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2023 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <loc.h>
+#include <pcut/pcut.h>
+
+PCUT_INIT;
+
+PCUT_TEST_SUITE(loc);
+
+/** loc_server_register() can be called multiple times */
+PCUT_TEST(server_register)
+{
+	errno_t rc;
+	loc_srv_t *sa, *sb;
+	service_id_t svca, svcb;
+	char *na, *nb;
+	char *sna, *snb;
+
+	rc = loc_server_register("test-a", &sa);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_server_register("test-b", &sb);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	// XXX Without a unique name this is not reentrant
+	rc = loc_service_register(sa, "test/libc-service-a", &svca);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	// XXX Without a unique name this is not reentrant
+	rc = loc_service_register(sb, "test/libc-service-b", &svcb);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = loc_service_get_name(svca, &na);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_STR_EQUALS("test/libc-service-a", na);
+
+	rc = loc_service_get_server_name(svca, &sna);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_STR_EQUALS("test-a", sna);
+
+	rc = loc_service_get_name(svcb, &nb);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_STR_EQUALS("test/libc-service-b", nb);
+
+	rc = loc_service_get_server_name(svcb, &snb);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_STR_EQUALS("test-b", snb);
+
+	rc = loc_service_unregister(sa, svca);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	rc = loc_service_unregister(sb, svcb);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	loc_server_unregister(sa);
+	loc_server_unregister(sb);
+}
+
+PCUT_EXPORT(loc);
Index: uspace/lib/c/test/main.c
===================================================================
--- uspace/lib/c/test/main.c	(revision 4c6fd56b8079778d8d40e0d5ffc6a1e8e8ad2b5b)
+++ uspace/lib/c/test/main.c	(revision 5afc1aab1cfdfe1ff186c56e8dd269294e23fdb6)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2023 Jiri Svoboda
  * Copyright (c) 2014 Vojtech Horky
  * All rights reserved.
@@ -42,4 +43,5 @@
 PCUT_IMPORT(imath);
 PCUT_IMPORT(inttypes);
+PCUT_IMPORT(loc);
 PCUT_IMPORT(mem);
 PCUT_IMPORT(odict);
