+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
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
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
/* Default configuration file */
#undef SILC_SERVER_CONFIG_FILE
+/* Multi-thread support */
+#undef SILC_THREADS
+
/* Default paths */
#undef SILC_ETCDIR
#undef SILC_HELPDIR
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
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.
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
#
#include <regex.h>
#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
#endif /* !SILC_WIN32 */
#ifndef HAVE_GETOPT_LONG
#include "silcpkcs.h"
/* SILC util library includes */
+#include "silcmutex.h"
+#include "silcthread.h"
#include "silchashtable.h"
#include "silclog.h"
#include "silcmemory.h"
--- /dev/null
+/****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
--- /dev/null
+/****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
silcunixschedule.c \
silcunixnet.c \
silcunixutil.c \
- silcunixsockconn.c
+ silcunixsockconn.c \
+ silcunixmutex.c \
+ silcunixthread.c
include $(top_srcdir)/Makefile.defines.in
--- /dev/null
+/*
+
+ 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 */
--- /dev/null
+/*
+
+ 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 */