+Sat Jan 27 22:37:30 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added SilcRwLock API, a read/write lock. Affected files are
+ lib/silcutil/silcmutex.h and in lib/silcutil/[unix|win32|symbian]/.
+
Wed Jan 24 18:55:21 EET 2007 Pekka Riikonen <priikone@silcnet.org>
* Merged Irssi SVN (irssi 0.8.11). Affected files in apps/irssi/.
* Implemented PKCS #1 with appendix with hash OID in the
signature. Affected files are lib/silccrypt/silcpkcs1.[ch],
- lib/silccrypt/silchash.[ch] and
+ lib/silccrypt/silchash.[ch] and
lib/silcasn1/silcasn1[_encode|decode].[ch].
Sun Jan 14 23:12:41 EET 2007 Pekka Riikonen <priikone@silcnet.org>
No need to make it silcutil/unix/ specific. Add them to generic
silcutil.c.
+ o Fix universal time decoding (doesn't accept all forms) in silctime.c.
+
o silc_stringprep to non-allocating version.
o Compression routines are missing. The protocol supports packet
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2005 Pekka Riikonen
+ Copyright (C) 2001 - 2007 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
*
* DESCRIPTION
*
- * Interface for the SILC Mutex locking implementation. This is platform
- * independent mutual exclusion interface for applications that need
- * concurrency control.
+ * Interface for mutual exclusion locks and read/write locks. This is
+ * platform independent interface for applications that need concurrency
+ * control.
*
***/
***/
typedef struct SilcMutexStruct *SilcMutex;
+/****s* silcutil/SilcMutexAPI/SilcRwLock
+ *
+ * NAME
+ *
+ * typedef struct SilcRwLockStruct *SilcRwLock;
+ *
+ * DESCRIPTION
+ *
+ * This context is the actual SILC read/write lock and is allocated
+ * by silc_rwlock_alloc and given as argument to all silc_rwlock_*
+ * functions. It is freed by the silc_rwlock_free function.
+ *
+ ***/
+typedef struct SilcRwLockStruct *SilcRwLock;
+
/****f* silcutil/SilcMutexAPI/silc_mutex_alloc
*
* SYNOPSIS
***/
void silc_mutex_assert_locked(SilcMutex mutex);
+/****f* silcutil/SilcMutexAPI/silc_rwlock_alloc
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_rwlock_alloc(SilcRwLock *rwlock);
+ *
+ * DESCRIPTION
+ *
+ * Allocates SILC read/write lock. The read/write lock must be allocated
+ * before it can be used. It is freed by the silc_rwlock_free function.
+ * This returns TRUE and allocated read/write lock in to the `rwlock' and
+ * FALSE on error.
+ *
+ ***/
+SilcBool silc_rwlock_alloc(SilcRwLock *rwlock);
+
+/****f* silcutil/SilcRwLockAPI/silc_rwlock_free
+ *
+ * SYNOPSIS
+ *
+ * void silc_rwlock_free(SilcRwLock rwlock);
+ *
+ * DESCRIPTION
+ *
+ * Free SILC Rwlock object and frees all allocated memory. If `rwlock'
+ * is NULL this function has no effect.
+ *
+ ***/
+void silc_rwlock_free(SilcRwLock rwlock);
+
+/****f* silcutil/SilcRwLockAPI/silc_rwlock_rdlock
+ *
+ * SYNOPSIS
+ *
+ * void silc_rwlock_rdlock(SilcRwLock rwlock);
+ *
+ * DESCRIPTION
+ *
+ * Acquires read lock of the read/write lock `rwlock'. If the `rwlock'
+ * is locked by a writer the current thread will block until the other
+ * thread has issued silc_rwlock_unlock for the `rwlock'. This function
+ * may be called multiple times to acquire the read lock. There must be
+ * same amount of silc_rwlock_unlock calls. If `rwlock' is NULL this
+ * function has no effect.
+ *
+ ***/
+void silc_rwlock_rdlock(SilcRwLock rwlock);
+
+/****f* silcutil/SilcRwLockAPI/silc_rwlock_wrlock
+ *
+ * SYNOPSIS
+ *
+ * void silc_rwlock_wrlock(SilcRwLock rwlock);
+ *
+ * DESCRIPTION
+ *
+ * Acquires write lock of the read/write lock `rwlock'. If the `rwlock'
+ * is locked by a writer or a reader the current thread will block until
+ * the other thread(s) have issued silc_rwlock_unlock for the `rwlock'.
+ * If `rwlock' is NULL this function has no effect.
+ *
+ ***/
+void silc_rwlock_wrlock(SilcRwLock rwlock);
+
+/****f* silcutil/SilcRwLockAPI/silc_rwlock_unlock
+ *
+ * SYNOPSIS
+ *
+ * void silc_rwlock_unlock(SilcRwLock rwlock);
+ *
+ * DESCRIPTION
+ *
+ * Releases the lock of the read/write lock `rwlock'. If `rwlock' was
+ * locked by a writer this will release the writer lock. Otherwise this
+ * releases the reader lock. If `rwlock' is NULL this function has no
+ * effect.
+ *
+ ***/
+void silc_rwlock_unlock(SilcRwLock rwlock);
+
#endif
#endif /* SILC_THREADS */
}
+/***************************** SILC Rwlock API *****************************/
+
+/* SILC read/write lock structure */
+struct SilcRwLockStruct {
+#ifdef SILC_THREADS
+ SilcMutex mutex;
+ SilcCond cond;
+#endif /* SILC_THREADS */
+ unsigned int readers : 31;
+ unsigned int locked : 1;
+};
+
+SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
+{
+#ifdef SILC_THREADS
+ *rwlock = (SilcRwLock)silc_calloc(1, sizeof(**rwlock));
+ if (!(*rwlock))
+ return FALSE;
+ if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
+ silc_free(*rwlock);
+ return FALSE;
+ }
+ if (!silc_cond_alloc(&(*rwlock)->cond)) {
+ silc_mutex_free((*rwlock)->mutex);
+ silc_free(*rwlock);
+ return FALSE;
+ }
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_free(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ silc_mutex_free(rwlock->mutex);
+ silc_cond_free(rwlock->cond);
+ silc_free(rwlock);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_rdlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ silc_mutex_lock(rwlock->mutex);
+ rwlock->readers++;
+ silc_mutex_unlock(rwlock->mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_wrlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ silc_mutex_lock(rwlock->mutex);
+ while (rwlock->readers > 0)
+ silc_cond_wait(rwlock->cond, rwlock->mutex);
+ rwlock->locked = TRUE;
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_unlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ if (rwlock->locked) {
+ /* Unlock writer */
+ rwlock->locked = FALSE;
+ silc_mutex_unlock(rwlock->mutex);
+ return;
+ }
+
+ /* Unlock reader */
+ silc_mutex_lock(rwlock->mutex);
+ rwlock->readers--;
+ silc_cond_broadcast(rwlock->cond);
+ silc_mutex_unlock(rwlock->mutex);
+ }
+#endif /* SILC_THREADS */
+}
/****************************** SILC Cond API *******************************/
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2006 Pekka Riikonen
+ Copyright (C) 2001 - 2007 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
#endif /* SILC_THREADS */
}
+/***************************** SILC Rwlock API ******************************/
+
+/* SILC read/write lock structure */
+struct SilcRwLockStruct {
+#ifdef SILC_THREADS
+ pthread_rwlock_t rwlock;
+#else
+ void *tmp;
+#endif /* SILC_THREADS */
+};
+
+SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
+{
+#ifdef SILC_THREADS
+ *rwlock = silc_calloc(1, sizeof(**rwlock));
+ if (*rwlock == NULL)
+ return FALSE;
+ pthread_rwlock_init(&(*rwlock)->rwlock, NULL);
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_free(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ pthread_rwlock_destroy(&rwlock->rwlock);
+ silc_free(rwlock);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_rdlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock)
+ pthread_rwlock_rdlock(&rwlock->rwlock);
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_wrlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock)
+ pthread_rwlock_wrlock(&rwlock->rwlock);
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_unlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock)
+ pthread_rwlock_unlock(&rwlock->rwlock);
+#endif /* SILC_THREADS */
+}
/****************************** SILC Cond API *******************************/
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2006 Pekka Riikonen
+ Copyright (C) 2001 - 2007 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
}
+/***************************** SILC Rwlock API ******************************/
+
+/* SILC read/write lock structure */
+struct SilcRwLockStruct {
+#ifdef SILC_THREADS
+ SilcMutex mutex;
+ SilcCond cond;
+#endif /* SILC_THREADS */
+ unsigned int readers : 31;
+ unsigned int locked : 1;
+};
+
+SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
+{
+#ifdef SILC_THREADS
+ *rwlock = silc_calloc(1, sizeof(**rwlock));
+ if (!(*rwlock))
+ return FALSE;
+ if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
+ silc_free(*rwlock);
+ return FALSE;
+ }
+ if (!silc_cond_alloc(&(*rwlock)->cond)) {
+ silc_mutex_free((*rwlock)->mutex);
+ silc_free(*rwlock);
+ return FALSE;
+ }
+ return TRUE;
+#else
+ return FALSE;
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_free(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (mutex) {
+ silc_mutex_free(rwlock->mutex);
+ silc_cond_free(rwlock->cond);
+ silc_free(rwlock);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_rdlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ silc_mutex_lock(rwlock->mutex);
+ rwlock->readers++;
+ silc_mutex_unlock(rwlock->mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_wrlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ silc_mutex_lock(rwlock->mutex);
+ while (rwlock->readers > 0)
+ silc_cond_wait(rwlock->cond, rwlock->mutex);
+ rwlock->locked = TRUE;
+ }
+#endif /* SILC_THREADS */
+}
+
+void silc_rwlock_unlock(SilcRwLock rwlock)
+{
+#ifdef SILC_THREADS
+ if (rwlock) {
+ if (rwlock->locked) {
+ /* Unlock writer */
+ rwlock->locked = FALSE;
+ silc_mutex_unlock(rwlock->mutex);
+ return;
+ }
+
+ /* Unlock reader */
+ silc_mutex_lock(rwlock->mutex);
+ rwlock->readers--;
+ silc_cond_broadcast(rwlock->cond);
+ silc_mutex_unlock(rwlock->mutex);
+ }
+#endif /* SILC_THREADS */
+}
+
+
/**************************** SILC Cond API ******************************/
/* SILC Conditional Variable context */
}
}
#endif /* SILC_THREADS*/
+ return TRUE;
}