summaryrefslogtreecommitdiff
path: root/p11-kit/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'p11-kit/util.c')
-rw-r--r--p11-kit/util.c188
1 files changed, 155 insertions, 33 deletions
diff --git a/p11-kit/util.c b/p11-kit/util.c
index fdf434b..eab0b13 100644
--- a/p11-kit/util.c
+++ b/p11-kit/util.c
@@ -36,6 +36,7 @@
#include "config.h"
+#include "debug.h"
#include "p11-kit.h"
#include "private.h"
#include "util.h"
@@ -46,6 +47,18 @@
#include <stdio.h>
#include <string.h>
+/*
+ * This is the mutex that protects the global data of this library
+ * and the pkcs11 proxy module. Note that we *never* call into our
+ * underlying pkcs11 modules while holding this mutex. Therefore it
+ * doesn't have to be recursive and we can keep things simple.
+ */
+mutex_t _p11_mutex;
+
+#ifdef OS_UNIX
+pthread_once_t _p11_once;
+#endif
+
/**
* SECTION:p11-kit-future
* @title: Future
@@ -56,9 +69,6 @@
* MACRO. See the p11-kit.h header for more details.
*/
-#define MAX_MESSAGE 512
-static pthread_once_t key_once = PTHREAD_ONCE_INIT;
-static pthread_key_t message_buffer_key = 0;
static int print_messages = 1;
void*
@@ -143,44 +153,34 @@ p11_kit_space_strdup (const unsigned char *string, size_t max_length)
}
static void
-create_message_buffer_key (void)
-{
- pthread_key_create (&message_buffer_key, free);
-}
-
-static void
store_message_buffer (const char* msg, size_t length)
{
- char *thread_buf;
+ p11_local *local;
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (!thread_buf) {
- thread_buf = malloc (MAX_MESSAGE);
- pthread_setspecific (message_buffer_key, thread_buf);
+ local = _p11_library_get_thread_local ();
+ if (local != NULL) {
+ memcpy (local->message, msg, length);
+ local->message[length] = 0;
}
-
- memcpy (thread_buf, msg, length);
- thread_buf[length] = 0;
}
void
_p11_message (const char* msg, ...)
{
- char buffer[MAX_MESSAGE];
+ char buffer[P11_MAX_MESSAGE];
va_list va;
size_t length;
va_start (va, msg);
- length = vsnprintf (buffer, MAX_MESSAGE - 1, msg, va);
+ length = vsnprintf (buffer, P11_MAX_MESSAGE - 1, msg, va);
va_end (va);
/* Was it truncated? */
- if (length > MAX_MESSAGE - 1)
- length = MAX_MESSAGE - 1;
+ if (length > P11_MAX_MESSAGE - 1)
+ length = P11_MAX_MESSAGE - 1;
buffer[length] = 0;
/* If printing is not disabled, just print out */
@@ -220,20 +220,18 @@ p11_kit_be_quiet (void)
const char*
p11_kit_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- return thread_buf && thread_buf[0] ? thread_buf : NULL;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ return local && local->message[0] ? local->message : NULL;
}
void
_p11_kit_clear_message (void)
{
- char *thread_buf;
- pthread_once (&key_once, create_message_buffer_key);
- thread_buf = pthread_getspecific (message_buffer_key);
- if (thread_buf != NULL)
- thread_buf[0] = 0;
+ p11_local *local;
+ local = _p11_library_get_thread_local ();
+ if (local != NULL)
+ local->message[0] = 0;
}
void
@@ -246,3 +244,127 @@ _p11_kit_default_message (CK_RV rv)
store_message_buffer (msg, strlen (msg));
}
}
+
+#ifdef OS_UNIX
+
+static pthread_key_t thread_local = 0;
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ p11_local *local;
+
+ _p11_library_init_once ();
+
+ local = pthread_getspecific (thread_local);
+ if (local == NULL) {
+ local = calloc (1, sizeof (p11_local));
+ pthread_setspecific (thread_local, local);
+ }
+
+ return local;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ pthread_key_create (&thread_local, free);
+}
+
+void
+_p11_library_uninit (void)
+{
+ pthread_key_delete (thread_local);
+ mutex_uninit (&_p11_mutex);
+}
+
+#endif /* OS_UNIX */
+
+#ifdef OS_WIN32
+
+static DWORD thread_local = TLS_OUT_OF_INDEXES;
+
+BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID);
+
+p11_local *
+_p11_library_get_thread_local (void)
+{
+ LPVOID data;
+
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return NULL;
+
+ data = TlsGetValue (thread_local);
+ if (data == NULL) {
+ data = LocalAlloc (LPTR, sizeof (p11_local));
+ TlsSetValue (thread_local, data);
+ }
+
+ return (p11_local *)data;
+}
+
+void
+_p11_library_init (void)
+{
+ debug_init ();
+ mutex_init (&_p11_mutex);
+ thread_local = TlsAlloc ();
+}
+
+static void
+free_tls_value (LPVOID data)
+{
+ p11_local *local = data;
+ if (local->last_error)
+ LocalFree (local->last_error);
+ LocalFree (data);
+}
+
+void
+_p11_library_uninit (void)
+{
+ LPVOID data;
+
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ TlsFree (thread_local);
+ }
+ mutex_uninit (&_p11_mutex);
+}
+
+BOOL WINAPI
+DllMain (HINSTANCE instance,
+ DWORD reason,
+ LPVOID reserved)
+{
+ LPVOID data;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ _p11_library_init ();
+ if (thread_local == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ break;
+
+ case DLL_THREAD_DETACH:
+ if (thread_local != TLS_OUT_OF_INDEXES) {
+ data = TlsGetValue (thread_local);
+ free_tls_value (data);
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ _p11_library_uninit ();
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif /* OS_WIN32 */