Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision 304faab43fc88f48106504167b2c003902c4e45f)
+++ uspace/lib/c/generic/loc.c	(revision 786bd568fef4358d3eb0f23391c4c44ea260420b)
@@ -47,4 +47,5 @@
 static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
 static bool loc_callback_created = false;
+static loc_cat_change_cb_t cat_change_cb = NULL;
 
 static async_sess_t *loc_supp_block_sess = NULL;
@@ -54,10 +55,6 @@
 static async_sess_t *loc_consumer_sess = NULL;
 
-static loc_cat_change_cb_t cat_change_cb = NULL;
-
 static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	loc_cat_change_cb_t cb_fun;
-	
 	while (true) {
 		ipc_call_t call;
@@ -69,21 +66,19 @@
 		}
 		
-		int retval;
-		
 		switch (IPC_GET_IMETHOD(call)) {
 		case LOC_EVENT_CAT_CHANGE:
 			fibril_mutex_lock(&loc_callback_mutex);
-			cb_fun = cat_change_cb;
-			if (cb_fun != NULL) {
+			loc_cat_change_cb_t cb_fun = cat_change_cb;
+			fibril_mutex_unlock(&loc_callback_mutex);
+			
+			async_answer_0(callid, EOK);
+			
+			if (cb_fun != NULL)
 				(*cb_fun)();
-			}
-			fibril_mutex_unlock(&loc_callback_mutex);
-			retval = 0;
+			
 			break;
 		default:
-			retval = ENOTSUP;
+			async_answer_0(callid, ENOTSUP);
 		}
-		
-		async_answer_0(callid, retval);
 	}
 }
@@ -101,36 +96,34 @@
 }
 
+/** Create callback
+ *
+ * Must be called with loc_callback_mutex locked.
+ *
+ * @return EOK on success.
+ *
+ */
 static int loc_callback_create(void)
 {
-	async_exch_t *exch;
-	sysarg_t retval;
-	int rc = EOK;
-
-	fibril_mutex_lock(&loc_callback_mutex);
-	
 	if (!loc_callback_created) {
-		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		async_exch_t *exch =
+		    loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
 		
 		ipc_call_t answer;
 		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
-		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		int rc = async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
 		loc_exchange_end(exch);
 		
+		if (rc != EOK)
+			return rc;
+		
+		sysarg_t retval;
 		async_wait_for(req, &retval);
-		if (rc != EOK)
-			goto done;
-		
-		if (retval != EOK) {
-			rc = retval;
-			goto done;
-		}
+		if (retval != EOK)
+			return retval;
 		
 		loc_callback_created = true;
 	}
 	
-	rc = EOK;
-done:
-	fibril_mutex_unlock(&loc_callback_mutex);
-	return rc;
+	return EOK;
 }
 
@@ -795,22 +788,18 @@
     sysarg_t **data, size_t *count)
 {
-	service_id_t *ids;
-	size_t act_size;
-	size_t alloc_size;
-	int rc;
-
 	*data = NULL;
-	act_size = 0;	/* silence warning */
-
-	rc = loc_category_get_ids_once(method, arg1, NULL, 0,
+	*count = 0;
+	
+	size_t act_size = 0;
+	int rc = loc_category_get_ids_once(method, arg1, NULL, 0,
 	    &act_size);
 	if (rc != EOK)
 		return rc;
-
-	alloc_size = act_size;
-	ids = malloc(alloc_size);
+	
+	size_t alloc_size = act_size;
+	service_id_t *ids = malloc(alloc_size);
 	if (ids == NULL)
 		return ENOMEM;
-
+	
 	while (true) {
 		rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
@@ -818,16 +807,14 @@
 		if (rc != EOK)
 			return rc;
-
+		
 		if (act_size <= alloc_size)
 			break;
-
-		alloc_size *= 2;
-		free(ids);
-
-		ids = malloc(alloc_size);
+		
+		alloc_size = act_size;
+		ids = realloc(ids, alloc_size);
 		if (ids == NULL)
 			return ENOMEM;
 	}
-
+	
 	*count = act_size / sizeof(category_id_t);
 	*data = ids;
@@ -867,8 +854,13 @@
 int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
 {
-	if (loc_callback_create() != EOK)
+	fibril_mutex_lock(&loc_callback_mutex);
+	if (loc_callback_create() != EOK) {
+		fibril_mutex_unlock(&loc_callback_mutex);
 		return EIO;
-
+	}
+	
 	cat_change_cb = cb_fun;
+	fibril_mutex_unlock(&loc_callback_mutex);
+	
 	return EOK;
 }
