updates.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 7 Jul 2001 21:58:51 +0000 (21:58 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 7 Jul 2001 21:58:51 +0000 (21:58 +0000)
CHANGES
TODO
acconfig.h.pre
configure.in.pre
includes/silcincludes.h
lib/silcutil/silcmutex.h [new file with mode: 0644]
lib/silcutil/silcthread.h [new file with mode: 0644]
lib/silcutil/unix/Makefile.am
lib/silcutil/unix/silcunixmutex.c [new file with mode: 0644]
lib/silcutil/unix/silcunixthread.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 15cf29f1a50d83cf92666240905efc1e62aeee63..4e515e65cf2670e0dd9f0b497c6e527e7ce0ded0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+Sun Jul  8 00:18:15 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Defined SILC Mutex API and SILC Thread API and implemented
+         them for Unix.  Affected files are
+         lib/silcutil/silcmutex.h, lib/silcutil/silcthread.h,
+         lib/silcutil/unix/silcunixmutex.c and
+         lib/silcutil/unix/silcunixthread.c.
+
 Sat Jul  7 14:40:31 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the silc_server_remove_clients_by_server's channel
diff --git a/TODO b/TODO
index 08a77285f3e5be1b96edbd58994d7f895d20dd7e..b5a01159025e574f3f6bf5b64456dfd1bd49037b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -91,6 +91,8 @@ TODO/bugs In SILC Server
 TODO/bugs In SILC Libraries
 ===========================
 
+ o Complete the SILC Mutex API and SILC Thread API.
+
  o Incomplete IPv6 support:
 
        o All network routines in lib/silcutil/silcnet.[ch] does not
@@ -132,18 +134,6 @@ TODO In SILC Protocol
 TODO After 1.0
 ==============
 
- o Pthreads support.  A lot of problems are solved with server (and with
-   client as well) if we add pthread support.  We can forget things such
-   as non-blocking connecting etc, and we can do things such as DNS/IP
-   lookups async.  The server itself also benefits great deal from 
-   threads, especially from performance point of view.
-
-   But, this is not a small task and almost entire SILC Library has to
-   be made re-entrant.  Own API is probably added for the threads support
-   to make changes in the future as painless as possible.  So the API 
-   would have things like silc_mutex_lock, silc_mutex_unlock and 
-   friends...
-
  o X.509 certificate support.  SILC protocol supports certificates and
    it would be great to have support for them.  This is a big task as
    support has to be made for ASN.1 as well.  I've looked into OpenSSL 
index ce215431461d49c95a94cbe454d03ff436f29a58..2e40f0c7e6154f9c9dc9c65bcbaa63fc3ad8f381 100644 (file)
@@ -10,6 +10,9 @@
 /* Default configuration file */
 #undef SILC_SERVER_CONFIG_FILE
 
+/* Multi-thread support */
+#undef SILC_THREADS
+
 /* Default paths */
 #undef SILC_ETCDIR
 #undef SILC_HELPDIR
index 80b8dec82167cd6b7c522648b428102fb71dfc34..23e6da76e54640f1b99a19930513ebd0641c4033 100644 (file)
@@ -67,6 +67,7 @@ AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h netdb.h)
 AC_CHECK_HEADERS(pwd.h grp.h termcap.h paths.h)
 AC_CHECK_HEADERS(ncurses.h signal.h ctype.h regex.h)
 AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h)
+AC_CHECK_HEADERS(pthread.h)
 
 # Data type checking
 AC_TYPE_SIGNAL
@@ -291,6 +292,7 @@ AC_CHECK_FUNCS(mlock munlock)
 AC_CHECK_FUNCS(chmod stat fstat getenv putenv strerror ctime gettimeofday)
 AC_CHECK_FUNCS(getpid getgid getsid getpgid getpgrp getuid)
 AC_CHECK_FUNCS(strchr strstr strcpy strncpy memcpy memset memmove)
+AC_CHECK_FUNCS(pthread_create)
 
 # SIM support checking
 # XXX These needs to be changed as more supported platforms appear.
@@ -555,6 +557,28 @@ AC_ARG_ENABLE(debug,
 esac ], CFLAGS="-O2 -g $CFLAGS"
         AC_MSG_RESULT(no))
 
+# Pthread checking
+AC_ARG_ENABLE(threads,
+[  --disable-threads       Do not compile with multi-thread support],
+[ case "${enableval}" in
+  yes)
+    AC_DEFINE(SILC_THREADS)
+    AM_CONDITIONAL(SILC_THREADS)
+    want_threads=true
+    ;;
+  *)
+    want_threads=false
+    ;;
+esac ], AC_DEFINE(SILC_THREADS)
+        AM_CONDITIONAL(SILC_THREADS)
+        want_threads=true)
+
+if test x$want_threads = xtrue; then
+  AC_TRY_COMPILE([#include <pthread.h>],
+                [pthread_attr_t attr; pthread_attr_init(&attr);],
+                LIBS="$LIBS -lpthread")
+fi
+
 #
 # Other configure scripts
 #
index 1c4ef761c8fa2c9fd2df20d056a5e92d09d68258..6ffb7186c281f520de3dbffad0a86f34781aa05b 100644 (file)
 #include <regex.h>
 #endif
 
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
 #endif                         /* !SILC_WIN32 */
 
 #ifndef HAVE_GETOPT_LONG
@@ -214,6 +218,8 @@ typedef uint32 * void *;
 #include "silcpkcs.h"
 
 /* SILC util library includes */
+#include "silcmutex.h"
+#include "silcthread.h"
 #include "silchashtable.h"
 #include "silclog.h"
 #include "silcmemory.h"
diff --git a/lib/silcutil/silcmutex.h b/lib/silcutil/silcmutex.h
new file mode 100644 (file)
index 0000000..89ee8a5
--- /dev/null
@@ -0,0 +1,119 @@
+/****h* silcutil/silcmutex.h
+ *
+ * NAME
+ *
+ * silcmutex.h
+ *
+ * COPYRIGHT
+ *
+ * Author: Pekka Riikonen <priikone@silcnet.org>
+ *
+ * Copyright (C) 2001 Pekka Riikonen
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * DESCRIPTION
+ *
+ * Interface for the SILC Mutex locking implementation. This is platform
+ * independent mutual exclusion interface for applications that need 
+ * concurrency control.
+ *
+ */
+
+#ifndef SILCMUTEX_H
+#define SILCMUTEX_H
+
+/* Prototypes */
+
+/****s* silcutil/SilcMutexAPI/SilcMutex
+ *
+ * NAME
+ * 
+ *    typedef struct SilcMutexStruct *SilcMutex;
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual SILC Mutex and is allocated
+ *    by silc_mutex_alloc and given as argument to all silc_mutex_*
+ *    functions.  It is freed by the silc_mutex_free function.
+ *
+ ***/
+typedef struct SilcMutexStruct *SilcMutex;
+
+/****f* silcutil/SilcMutexAPI/silc_mutex_alloc
+ *
+ * SYNOPSIS
+ *
+ *    SilcMutex silc_mutex_alloc(void);
+ *
+ * DESCRIPTION
+ *
+ *    Allocates SILC Mutex object.  The mutex object must be allocated
+ *    before it can be used.  It is freed by the silc_mutex_free function.
+ *
+ ***/
+SilcMutex silc_mutex_alloc(void);
+
+/****f* silcutil/SilcMutexAPI/silc_mutex_free
+ *
+ * SYNOPSIS
+ *
+ *    void silc_mutex_free(SilcMutex mutex);
+ *
+ * DESCRIPTION
+ *
+ *    Free SILC Mutex object and frees all allocated memory.
+ *
+ ***/
+void silc_mutex_free(SilcMutex mutex);
+
+/****f* silcutil/SilcMutexAPI/silc_mutex_lock
+ *
+ * SYNOPSIS
+ *
+ *    void silc_mutex_lock(SilcMutex mutex);
+ *
+ * DESCRIPTION
+ *
+ *    Locks the mutex. If the mutex is locked by another thread the
+ *    current thread will block until the other thread has issued
+ *    silc_mutex_unlock for the mutex.
+ *
+ * NOTES
+ *
+ *    The caller must not call silc_mutex_lock for mutex that has been
+ *    already locked in the current thread.  In this case deadlock will
+ *    occur.
+ *
+ ***/
+void silc_mutex_lock(SilcMutex mutex);
+
+/****f* silcutil/SilcMutexAPI/silc_mutex_unlock
+ *
+ * SYNOPSIS
+ *
+ *    void silc_mutex_unlock(SilcMutex mutex);
+ *
+ * DESCRIPTION
+ *
+ *    Unlocks the mutex and thus releases it for another threads that
+ *    may be waiting for the lock.
+ *
+ * NOTES
+ *
+ *    The caller must not call the silc_mutex_unlock for an unlocked
+ *    mutex or mutex not locked by the current thread.  It is fatal
+ *    error if this occurs.
+ *
+ ***/
+void silc_mutex_unlock(SilcMutex mutex);
+
+#endif
diff --git a/lib/silcutil/silcthread.h b/lib/silcutil/silcthread.h
new file mode 100644 (file)
index 0000000..5d4932d
--- /dev/null
@@ -0,0 +1,148 @@
+/****h* silcutil/silcthread.h
+ *
+ * NAME
+ *
+ * silcmutex.h
+ *
+ * COPYRIGHT
+ *
+ * Author: Pekka Riikonen <priikone@silcnet.org>
+ *
+ * Copyright (C) 2001 Pekka Riikonen
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * DESCRIPTION
+ *
+ * Interface for SILC Thread implementation. This is platform independent
+ * implementation of threads for applications needing concurrent execution
+ * with the application's main thread. The threads created with this 
+ * interface executes concurrently with the calling thread.
+ *
+ */
+
+#ifndef SILCTHREAD_H
+#define SILCTHREAD_H
+
+/* Prototypes */
+
+/****s* silcutil/SilcThreadAPI/SilcThread
+ *
+ * NAME
+ * 
+ *    typedef struct SilcThreadStruct *SilcThread;
+ *
+ * DESCRIPTION
+ *
+ *    This context is the actual SILC Thread and is returned by
+ *    the silc_thread_create functions, and given as arguments to
+ *    some of the silc_thread_* functions. This context and its
+ *    resources are released automatically when the thread exits.
+ *
+ ***/
+typedef void *SilcThread;
+
+/****f* silcutil/SilcThreadAPI/SilcThreadStart
+ *
+ * SYNOPSIS
+ *
+ *    typedef void *(*SilcThreadStart)(void *context);
+ *
+ * DESCRIPTION
+ *
+ *    A callback function that is called when the thread is created
+ *    by the silc_thread_create function.  This returns the return value
+ *    of the thread. If another thread is waiting this thread's
+ *    destruction with silc_thread_wait the returned value is passed
+ *    to that thread. The thread is destroyed when this function
+ *    returns.
+ *
+ ***/
+typedef void *(*SilcThreadStart)(void *context);
+
+/****f* silcutil/SilcThreadAPI/silc_thread_create
+ *
+ * SYNOPSIS
+ *
+ *    SilcThread silc_thread_create(SilcThreadStart start_func, void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Creates a new thread. The `start_func' with `context' will be
+ *    called if the thread was created. This function returns a pointer
+ *    to the thread or NULL if the thread could not be created.  All
+ *    resources of the returned pointer is freed automatically when the
+ *    thread exits.
+ *
+ *    If the `waitable' is set to TRUE then another thread can wait
+ *    this thread's destruction with silc_thread_wait. If it is set to
+ *    FALSE the thread is not waitable.
+ *
+ * NOTES
+ *
+ *    If the `waitable' is TRUE the thread's resources are not freed
+ *    when it exits until another thread has issued silc_thread_wait.
+ *    If the `waitable' is TRUE then another thread must always issue
+ *    silc_thread_wait to avoid memory leaks.
+ *
+ ***/
+SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
+                             bool waitable);
+
+/****f* silcutil/SilcThreadAPI/silc_thread_exit
+ *
+ * SYNOPSIS
+ *
+ *    void silc_thread_exit(void *exit_value);
+ *
+ * DESCRIPTION
+ *
+ *    Exits the current thread. This can be called to explicitly exit
+ *    the thread with `exit_value'. Another way to exit (destroy) the
+ *    current thread is to return from the SilcThreadStart function
+ *    with exit value. The exit value is passed to another thread if it
+ *    is waiting it with silc_thread_wait function.
+ *
+ ***/
+void silc_thread_exit(void *exit_value);
+
+/****f* silcutil/SilcThreadAPI/silc_thread_self
+ *
+ * SYNOPSIS
+ *
+ *    SilcThread silc_thread_self(void);
+ *
+ * DESCRIPTION
+ *
+ *    Returns a pointer of the current thread.
+ *
+ ***/
+SilcThread silc_thread_self(void);
+
+/****f* silcutil/SilcThreadAPI/silc_thread_wait
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_thread_wait(SilcThread thread, void **exit_value);
+ *
+ * DESCRIPTION
+ *
+ *    Waits until the thread indicated by `thread' finishes. This blocks
+ *    the execution of the current thread. The thread is finished if it
+ *    calls silc_thread_exit or is destroyed naturally. When the thread
+ *    exits its exit value is saved to `exit_value' and TRUE is returned.
+ *    If the `thread' is not waitable this will return immediately with
+ *    FALSE value.
+ *
+ ***/
+bool silc_thread_wait(SilcThread thread, void **exit_value);
+
+#endif
index bf019fe8c4c0ada72331ebefff96a163cd498f1b..1b5b1c81b732e5fca4eea0cd2d2a0f0a70620734 100644 (file)
@@ -24,6 +24,8 @@ libsilcunixutil_a_SOURCES =   \
        silcunixschedule.c      \
        silcunixnet.c           \
        silcunixutil.c          \
-       silcunixsockconn.c
+       silcunixsockconn.c      \
+       silcunixmutex.c         \
+       silcunixthread.c
 
 include $(top_srcdir)/Makefile.defines.in
diff --git a/lib/silcutil/unix/silcunixmutex.c b/lib/silcutil/unix/silcunixmutex.c
new file mode 100644 (file)
index 0000000..da802d5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+
+  silcunixmutex.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2001 Pekka Riikonen
+
+  This program 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 of the License, or
+  (at your option) any later version.
+  
+  This program 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.
+
+*/
+/* $Id: */
+
+#include "silcincludes.h"
+
+#ifdef SILC_THREADS
+
+/* SILC Mutex structure */
+struct SilcMutexStruct {
+  pthread_mutex_t mutex;
+};
+
+SilcMutex silc_mutex_alloc(void)
+{
+  SilcMutex mutex = silc_calloc(1, sizeof(*mutex));
+  pthread_mutex_init(&mutex->mutex, NULL);
+}
+
+void silc_mutex_free(SilcMutex mutex)
+{
+  pthread_mutex_destroy(&mutex->mutex);
+  silc_free(mutex);
+}
+
+void silc_mutex_lock(SilcMutex mutex)
+{
+  if (pthread_mutex_lock(&mutex->mutex))
+    assert(FALSE);
+}
+
+void silc_mutex_unlock(SilcMutex mutex)
+{
+  if (pthread_mutex_unlock(&mutex->mutex))
+    assert(FALSE);
+}
+
+#endif /* SILC_THREADS */
diff --git a/lib/silcutil/unix/silcunixthread.c b/lib/silcutil/unix/silcunixthread.c
new file mode 100644 (file)
index 0000000..b4fe5a0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+
+  silcunixthread.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2001 Pekka Riikonen
+
+  This program 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 of the License, or
+  (at your option) any later version.
+  
+  This program 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.
+
+*/
+/* $Id: */
+
+#include "silcincludes.h"
+
+#ifdef SILC_THREADS
+
+SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
+                             bool waitable)
+{
+  pthread_attr_t attr;
+  pthread_t thread;
+  int ret;
+
+  SILC_LOG_DEBUG(("Creating new thread"));
+
+  if (!start_func)
+    return NULL;
+
+  if (pthread_attr_init(&attr)) {
+    SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+    return NULL;
+  }
+
+  if (pthread_attr_setdetachstate(&attr,
+                                 waitable ? PTHREAD_CREATE_JOINABLE : 
+                                 PTHREAD_CREATE_DETACHED)) {
+    SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+    pthread_attr_destroy(&attr);
+    return NULL;
+  }
+
+  ret = pthread_create(&thread, &attr, (void * (*)(void *))start_func, 
+                      context);
+  if (ret) {
+    SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+    pthread_attr_destroy(&attr);
+    return NULL;
+  }
+
+  pthread_attr_destroy(&attr);
+
+  SILC_LOG_DEBUG(("Created thread %p", (SilcThread)ret));
+
+  return (SilcThread)ret;
+}
+
+void silc_thread_exit(void *exit_value)
+{
+  pthread_exit(NULL);
+}
+
+SilcThread silc_thread_self(void)
+{
+  pthread_t self = pthread_self();
+  return (SilcThread)self;
+}
+
+bool silc_thread_wait(SilcThread thread, void **exit_value)
+{
+  SILC_LOG_DEBUG(("Waiting for thread %p", thread));
+  if (!pthread_join(*(pthread_t *)thread, exit_value))
+    return TRUE;
+  return FALSE;
+}
+
+#endif /* SILC_THREADS */