(inet_ntoa): Complete rewrite. Now uses thread-specific memory in
authordrepper <drepper>
Mon, 31 Mar 1997 00:27:55 +0000 (00:27 +0000)
committerdrepper <drepper>
Mon, 31 Mar 1997 00:27:55 +0000 (00:27 +0000)
multi-threaded programs.

inet/inet_ntoa.c

index a37b1db..b6087a9 100644 (file)
@@ -1,59 +1,97 @@
-/*
- * Copyright (c) 1983, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)inet_ntoa.c        8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * Convert network-format internet address
- * to base 256 d.d.d.d representation.
- */
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+/* Convert Inet number to ASCII representation.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
 #include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <libc-lock.h>
+
+/* The interface of this function is completely stupid, it requires a
+   static buffer.  We relax this a bit in that we allow at least one
+   buffer for each thread.  */
+__libc_lock_define_initialized (static, lock);
+
+/* This is the key for the thread specific memory.  */
+static __libc_key_t key;
+
+/* Destructor for the thread-specific data.  */
+static void free_key_mem (void *mem);
+
 
 char *
-inet_ntoa(in)
-       struct in_addr in;
+inet_ntoa (struct in_addr in)
 {
-       static char b[18];
-       register char *p;
-
-       p = (char *)&in;
-#define        UC(b)   (((int)b)&0xff)
-       (void)snprintf(b, sizeof(b),
-           "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
-       return (b);
+  static char static_buf[18];
+  static int initialized = 0;
+  char *buffer = NULL;
+  unsigned char *bytes;
+
+  /* If we have not yet initialized the buffer do it now.  */
+  if (!initialized)
+    {
+      /* Make sure there is only one process doing the initialization.  */
+      __libc_lock_lock (lock);
+
+      if (!initialized)
+       {
+         if (__libc_key_create (&key, free_key_mem))
+           /* Creating the key failed.  This either means we run
+              have only a single-threaded application or something
+              really went wrong.  In any case use a static buffer
+              which is better than nothing.  */
+           buffer = static_buf;
+       }
+
+      __libc_lock_unlock (lock);
+    }
+
+  if (buffer == NULL)
+    {
+      /* We don't use the static buffer and so we have a key.  Use it
+        to get the thread-specific buffer.  */
+      buffer = __libc_getspecific (key);
+      if (buffer == NULL)
+       {
+         /* No buffer allocated so far.  */
+         buffer = malloc (18);
+         if (buffer == NULL)
+           /* No more memory available.  We use the static buffer.  */
+           buffer = static_buf;
+         else
+           __libc_setspecific (key, buffer);
+       }
+    }
+
+  bytes = (unsigned char *) &in;
+  snprintf (buffer, 18, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
+
+  return buffer;
+}
+
+
+static void
+free_key_mem (void *mem)
+{
+  free (mem);
+
+  /* And we must set the data to NULL so that the destructor is not
+     called again.  */
+  __libc_setspecific (key, NULL);
 }