summaryrefslogtreecommitdiffstats
path: root/lib/pthread_safe.c
diff options
context:
space:
mode:
authorpaulo <paul@bayleaf.org.uk>2010-02-04 15:09:00 +0000
committerpaulo <paul@bayleaf.org.uk>2010-02-04 15:09:00 +0000
commit2c9671af75453599104a36b30c4f9281104b1816 (patch)
treecb77b6bbbe1ecc0a549a39af602221b9de5282da /lib/pthread_safe.c
parentd8921b6522d8b55f3de87f90c4cdc0755acf8c7f (diff)
downloadquagga-2c9671af75453599104a36b30c4f9281104b1816.tar.bz2
quagga-2c9671af75453599104a36b30c4f9281104b1816.tar.xz
Thread safe versions of inet_ntoa and strerror.
Diffstat (limited to 'lib/pthread_safe.c')
-rw-r--r--lib/pthread_safe.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/pthread_safe.c b/lib/pthread_safe.c
new file mode 100644
index 00000000..a8da3a71
--- /dev/null
+++ b/lib/pthread_safe.c
@@ -0,0 +1,124 @@
+/* Quagga Pthreads support -- thread safe versions of standard functions
+ * Copyright (C) 2009 Chris Hall (GMCH), Highwayman
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* We use thread specific storeage to provide buufers for the _r versions
+ * of standard functions, so that the callers don't need to provide
+ * their own. The contents of a buffer will remain intact until another
+ * safe_ function is called on the same thread
+ */
+
+#include "pthread_safe.h"
+#include "qpthreads.h"
+#include "memory.h"
+
+#include <pthread.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+/* prototypes */
+static void destructor(void* data);
+static char * thread_buff(void);
+
+static pthread_key_t tsd_key;
+static const int buff_size = 1024;
+
+/* Module initialization, before any threads have been created */
+void
+safe_init_r(void)
+{
+ if (qpthreads_enabled)
+ {
+ int status;
+ status = pthread_key_create(&tsd_key, destructor);
+ if (status != 0)
+ zabort("Can't create thread specific data key");
+ }
+}
+
+/* Clean up */
+void
+safe_finish(void)
+{
+ if (qpthreads_enabled)
+ pthread_key_delete(tsd_key);
+}
+
+static void
+destructor(void* data)
+{
+ XFREE(MTYPE_TSD, data);
+}
+
+/* Thread safe version of strerror. Never returns NULL.
+ * Contents of result remains intact until another call of
+ * a safe_ function.
+ */
+const char *
+safe_strerror(int errnum)
+{
+ static const char * unknown = "Unknown error";
+ if (qpthreads_enabled)
+ {
+ char * buff = thread_buff();
+ int ret = strerror_r(errnum, buff, buff_size);
+
+ return (ret >= 0)
+ ? buff
+ : unknown;
+ }
+ else
+ {
+ const char *s = strerror(errnum);
+ return (s != NULL)
+ ? s
+ : unknown;
+ }
+}
+
+const char *
+safe_inet_ntoa (struct in_addr in)
+{
+ if (qpthreads_enabled)
+ return inet_ntop(AF_INET, &in, thread_buff(), buff_size);
+ else
+ return inet_ntoa(in);
+}
+
+/* Return the thread's buffer */
+static char *
+thread_buff(void)
+{
+ int ret;
+ char * buff = pthread_getspecific(tsd_key);
+ if (buff == NULL)
+ {
+ buff = XMALLOC(MTYPE_TSD, buff_size);
+ ret = pthread_setspecific(tsd_key, buff);
+ if (ret != 0)
+ zabort("Can't set thread specific data");
+ }
+
+ return buff;
+}