Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2011-11-10 20:19:02 -0500
committerEugene Tarassov2011-11-10 20:19:02 -0500
commita107edc216f94c5ec059fdf74541908bc7e979bb (patch)
treea0d9a448043cf5b969c2ede059b7d19a3aa64b71 /agent/tcf/framework/cache.c
parent07c7a005cded9e4b4ec842d756d0e4d79dade149 (diff)
downloadorg.eclipse.tcf.agent-a107edc216f94c5ec059fdf74541908bc7e979bb.tar.gz
org.eclipse.tcf.agent-a107edc216f94c5ec059fdf74541908bc7e979bb.tar.xz
org.eclipse.tcf.agent-a107edc216f94c5ec059fdf74541908bc7e979bb.zip
Agent code is moved into separate "agent" directory, all C code moved into "tcf" directory.
Diffstat (limited to 'agent/tcf/framework/cache.c')
-rw-r--r--agent/tcf/framework/cache.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/agent/tcf/framework/cache.c b/agent/tcf/framework/cache.c
new file mode 100644
index 00000000..c2b7ebe0
--- /dev/null
+++ b/agent/tcf/framework/cache.c
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ * You may elect to redistribute this code under either of these licenses.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * Abstract asynchronous data cache support.
+ */
+
+#include <config.h>
+#include <assert.h>
+#include <string.h>
+#include <framework/errors.h>
+#include <framework/exceptions.h>
+#include <framework/myalloc.h>
+#include <framework/events.h>
+#include <framework/trace.h>
+#include <framework/cache.h>
+
+typedef struct WaitingCacheClient {
+ CacheClient * client;
+ Channel * channel;
+ void * args;
+ size_t args_size;
+ int args_copy;
+#ifndef NDEBUG
+ const char * file;
+ int line;
+#endif
+} WaitingCacheClient;
+
+static WaitingCacheClient current_client = {0, 0, 0, 0, 0};
+static int client_exited = 0;
+static int cache_miss_cnt = 0;
+static WaitingCacheClient * wait_list_buf;
+static unsigned wait_list_max;
+static LINK cache_list;
+
+static void run_cache_client(void) {
+ Trap trap;
+
+ cache_miss_cnt = 0;
+ client_exited = 0;
+ if (set_trap(&trap)) {
+ current_client.client(current_client.args);
+ clear_trap(&trap);
+ assert(cache_miss_cnt == 0);
+ assert(client_exited);
+ }
+ else if (get_error_code(trap.error) != ERR_CACHE_MISS || client_exited || cache_miss_cnt == 0) {
+ trace(LOG_ALWAYS, "Unhandled exception in data cache client: %d %s", trap.error, errno_to_str(trap.error));
+ }
+ if (cache_miss_cnt == 0 && current_client.args_copy) loc_free(current_client.args);
+ memset(&current_client, 0, sizeof(current_client));
+ cache_miss_cnt = 0;
+ client_exited = 0;
+}
+
+void cache_enter(CacheClient * client, Channel * channel, void * args, size_t args_size) {
+ assert(is_dispatch_thread());
+ assert(client != NULL);
+ assert(channel != NULL);
+ assert(!is_channel_closed(channel));
+ assert(current_client.client == NULL);
+ current_client.client = client;
+ current_client.channel = channel;
+ current_client.args = args;
+ current_client.args_size = args_size;
+ current_client.args_copy = 0;
+ run_cache_client();
+}
+
+void cache_exit(void) {
+ assert(is_dispatch_thread());
+ assert(current_client.client != NULL);
+ assert(!client_exited);
+ if (cache_miss_cnt > 0) exception(ERR_CACHE_MISS);
+ client_exited = 1;
+}
+
+#ifdef NDEBUG
+void cache_wait(AbstractCache * cache) {
+#else
+void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
+#endif
+ assert(is_dispatch_thread());
+ assert(client_exited == 0);
+ if (current_client.client != NULL && cache_miss_cnt == 0) {
+ if (cache_list.next == NULL) list_init(&cache_list);
+ if (cache->wait_list_cnt >= cache->wait_list_max) {
+ cache->wait_list_max += 8;
+ cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient));
+ }
+ if (current_client.args != NULL && !current_client.args_copy) {
+ void * mem = loc_alloc(current_client.args_size);
+ memcpy(mem, current_client.args, current_client.args_size);
+ current_client.args = mem;
+ current_client.args_copy = 1;
+ }
+#ifndef NDEBUG
+ current_client.file = file;
+ current_client.line = line;
+#endif
+ if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list);
+ cache->wait_list_buf[cache->wait_list_cnt++] = current_client;
+ channel_lock(current_client.channel);
+ }
+#ifndef NDEBUG
+ else if (current_client.client == NULL) {
+ trace(LOG_ALWAYS, "cache_wait(): illegal cache access at %s:%d", file, line);
+ }
+#endif
+ cache_miss_cnt++;
+ exception(ERR_CACHE_MISS);
+}
+
+void cache_notify(AbstractCache * cache) {
+ unsigned i;
+ unsigned cnt = cache->wait_list_cnt;
+
+ assert(is_dispatch_thread());
+ if (cnt == 0) return;
+ list_remove(&cache->link);
+ cache->wait_list_cnt = 0;
+ if (wait_list_max < cnt) {
+ wait_list_max = cnt;
+ wait_list_buf = (WaitingCacheClient *)loc_realloc(wait_list_buf, cnt * sizeof(WaitingCacheClient));
+ }
+ memcpy(wait_list_buf, cache->wait_list_buf, cnt * sizeof(WaitingCacheClient));
+ for (i = 0; i < cnt; i++) {
+ current_client = wait_list_buf[i];
+ run_cache_client();
+ channel_unlock(wait_list_buf[i].channel);
+ }
+}
+
+Channel * cache_channel(void) {
+ return current_client.channel;
+}
+
+void cache_dispose(AbstractCache * cache) {
+ assert(is_dispatch_thread());
+ assert(cache->wait_list_cnt == 0);
+ assert(list_is_empty(&cache->link));
+ loc_free(cache->wait_list_buf);
+ memset(cache, 0, sizeof(*cache));
+}

Back to the top