# Configuration variables of the UCW library and their default values
-# (c) 2005--2009 Martin Mares <mj@ucw.cz>
+# (c) 2005--2010 Martin Mares <mj@ucw.cz>
# Version of the whole package
Set("UCW_VERSION" => "4.0.1-dev");
Set("CONFIG_DIRECT_IO");
Set("CONFIG_UCW_FB_DIRECT");
+# Use thread-local storage (needs GCC-support, default: auto-detect)
+# Set("CONFIG_UCW_TLS");
+
# Return success
1;
# UCW Library configuration system: parameters of the library
-# (c) 2005--2008 Martin Mares <mj@ucw.cz>
+# (c) 2005--2010 Martin Mares <mj@ucw.cz>
# (c) 2006 Robert Spalek <robert@ucw.cz>
# (c) 2008 Michal Vaner <vorner@ucw.cz>
Set("CONFIG_UCW_RADIX_SORTER_BITS" => 12);
}
+# Detect if thread-local storage is supported
+if (Get("CONFIG_UCW_THREADS")) {
+ TestBool("CONFIG_UCW_TLS", "Checking if GCC supports thread-local storage", sub {
+ if (UCW::Configure::C::TestCompile("__thread int i;\nint main(void) { return 0; }\n")) {
+ return 1;
+ } else {
+ return 0;
+ }
+ });
+}
+
PostConfig {
AtWrite {
UCW::Configure::C::ConfigHeader("ucw/autoconf.h", [
/*
* The UCW Library -- Threading Helpers
*
- * (c) 2006 Martin Mares <mj@ucw.cz>
+ * (c) 2006--2010 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
#endif
#endif
-static pthread_key_t ucwlib_context_key;
+/*** Library lock ***/
+
static pthread_mutex_t ucwlib_master_mutex;
-static void
-ucwlib_free_thread_context(void *p)
+void
+ucwlib_lock(void)
{
- xfree(p);
+ pthread_mutex_lock(&ucwlib_master_mutex);
}
-static void CONSTRUCTOR
-ucwlib_threads_init(void)
+void
+ucwlib_unlock(void)
{
- if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0)
- die("Cannot create pthread_key: %m");
- pthread_mutex_init(&ucwlib_master_mutex, NULL);
+ pthread_mutex_unlock(&ucwlib_master_mutex);
}
+/*** Thread identifiers ***/
+
static int
ucwlib_tid(void)
{
return tid;
}
-struct ucwlib_context *
-ucwlib_thread_context(void)
-{
- struct ucwlib_context *c = pthread_getspecific(ucwlib_context_key);
- if (!c)
- {
- c = xmalloc_zero(sizeof(*c));
- c->thread_id = ucwlib_tid();
- pthread_setspecific(ucwlib_context_key, c);
- }
- return c;
-}
+/*** Thread context ***/
-void
-ucwlib_lock(void)
-{
- pthread_mutex_lock(&ucwlib_master_mutex);
-}
+#ifdef CONFIG_UCW_TLS
-void
-ucwlib_unlock(void)
+__thread struct ucwlib_context ucwlib_context;
+
+int
+ucwlib_thread_id(struct ucwlib_context *c)
{
- pthread_mutex_unlock(&ucwlib_master_mutex);
+ if (!c->_thread_id)
+ c->_thread_id = ucwlib_tid();
+ return c->_thread_id;
}
#else
-struct ucwlib_context *
-ucwlib_thread_context(void)
+static pthread_key_t ucwlib_context_key;
+
+static void
+ucwlib_free_thread_context(void *p)
{
- static struct ucwlib_context ucwlib_context;
- return &ucwlib_context;
+ xfree(p);
}
-void
-ucwlib_lock(void)
+static void CONSTRUCTOR
+ucwlib_threads_init(void)
{
+ if (pthread_key_create(&ucwlib_context_key, ucwlib_free_thread_context) < 0)
+ die("Cannot create pthread_key: %m");
+ pthread_mutex_init(&ucwlib_master_mutex, NULL);
}
-void
-ucwlib_unlock(void)
+struct ucwlib_context *
+ucwlib_thread_context(void)
{
+ struct ucwlib_context *c = pthread_getspecific(ucwlib_context_key);
+ if (!c)
+ {
+ c = xmalloc_zero(sizeof(*c));
+ c->_thread_id = ucwlib_tid();
+ pthread_setspecific(ucwlib_context_key, c);
+ }
+ return c;
}
+#endif /* CONFIG_UCW_TLS */
+
+#else /* !CONFIG_UCW_THREADS */
+
+struct ucwlib_context default_ucwlib_context;
+
#endif
#ifdef TEST
{
ucwlib_lock();
ucwlib_unlock();
- msg(L_INFO, "tid=%d", ucwlib_thread_context()->thread_id);
+ msg(L_INFO, "tid=%d", ucwlib_thread_id(ucwlib_thread_context()));
return 0;
}
/*
* The UCW Library -- Threading Helpers
*
- * (c) 2006 Martin Mares <mj@ucw.cz>
+ * (c) 2006--2010 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
/* This structure holds per-thread data */
struct ucwlib_context {
- int thread_id; // Thread ID (either kernel tid or a counter)
+ int _thread_id; // Thread ID (either kernel tid or a counter, use ucwlib_thread_id())
int temp_counter; // Counter for fb-temp.c
struct asio_queue *io_queue; // Async I/O queue for fb-direct.c
ucw_sighandler_t *signal_handlers; // Signal handlers for sighandler.c
};
+#ifdef CONFIG_UCW_THREADS
+
+#ifdef CONFIG_UCW_TLS
+extern __thread struct ucwlib_context ucwlib_context;
+static inline struct ucwlib_context *ucwlib_thread_context(void) { return &ucwlib_context; }
+int ucwlib_thread_id(struct ucwlib_context *c);
+#else
struct ucwlib_context *ucwlib_thread_context(void);
+static inline int ucwlib_thread_id(struct ucwlib_context *c) { return c->_thread_id; }
+#endif
/* Global lock used for initialization, cleanup and other not so frequently accessed global state */
void ucwlib_lock(void);
void ucwlib_unlock(void);
-#ifdef CONFIG_UCW_THREADS
-
extern uns ucwlib_thread_stack_size;
+#else
+
+/* We have no threads, let's simulate the context and locking */
+
+extern struct ucwlib_context default_ucwlib_context;
+static inline struct ucwlib_context *ucwlib_thread_context(void) { return &default_ucwlib_context; }
+
+static inline int ucwlib_thread_id(struct ucwlib_context *c UNUSED) { return 0; }
+
+static inline void ucwlib_lock(void) { }
+static inline void ucwlib_unlock(void) { }
+
#endif
#endif