[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[hurd] 01/04: Replace internal semaphore implementation with posix semap
From: |
Samuel Thibault |
Subject: |
[hurd] 01/04: Replace internal semaphore implementation with posix semaphores |
Date: |
Mon, 24 Oct 2016 00:16:41 +0000 |
This is an automated email from the git hooks/post-receive script.
sthibault pushed a commit to branch dde
in repository hurd.
commit 7cdbac372625953228a363bd8a4a015c2b516a5b
Author: Samuel Thibault <address@hidden>
Date: Wed Oct 12 02:53:49 2016 +0200
Replace internal semaphore implementation with posix semaphores
* libddekit/thread.c: Include <semaphore.h>, do not include "list.h"
(struct _ddekit_private_data): Remove list and wakeupmsg fields.
(struct ddekit_sem): Replace content with just one sem_t.
(_thread_cleanup): Do not destroy wakeupmsg.msgh_remote_port.
(_create_wakeupmsg): Remove function.
(setup_thread): Do not initialize private_data->list, do not call
_create_wakeupmsg.
(_timedblock, _block, _thread_wakeup): Remove functions.
(_sem_timedwait_internal): Reimplement function using sem_timedwait and
sem_wait.
(ddekit_sem_init): Reimplement function using sem_init.
(ddekit_sem_deinit): Reimplement function using sem_destroy.
(ddekit_sem_down_try): Reimplement function using sem_trywait.
(ddekit_sem_up): Reimplement function using sem_post.
---
libddekit/thread.c | 208 ++++++++---------------------------------------------
1 file changed, 29 insertions(+), 179 deletions(-)
diff --git a/libddekit/thread.c b/libddekit/thread.c
index 8f7b3ed..17d553b 100644
--- a/libddekit/thread.c
+++ b/libddekit/thread.c
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <string.h>
#include <pthread.h>
+#include <semaphore.h>
#include <time.h>
#include <error.h>
#include <mach.h>
@@ -11,7 +12,6 @@
#include "ddekit/memory.h"
#include "ddekit/semaphore.h"
#include "ddekit/condvar.h"
-#include "list.h"
#include "ddekit/thread.h"
#define DDEKIT_THREAD_STACK_SIZE 0x2000 /* 8 KB */
@@ -19,11 +19,9 @@
//static struct ddekit_slab *ddekit_stack_slab = NULL;
struct _ddekit_private_data {
- struct list list;
ddekit_condvar_t *sleep_cond;
/* point to the thread who has the private data. */
struct ddekit_thread *thread;
- mach_msg_header_t wakeupmsg;
};
struct ddekit_thread {
@@ -35,57 +33,20 @@ struct ddekit_thread {
struct ddekit_sem
{
- pthread_spinlock_t lock;
- /* A list of thread waiting for the semaphore. */
- struct list head;
- int value;
+ sem_t sem;
};
static __thread struct ddekit_thread *thread_self;
static void _thread_cleanup ()
{
- mach_port_destroy (mach_task_self (),
- thread_self->private->wakeupmsg.msgh_remote_port);
ddekit_condvar_deinit (thread_self->private->sleep_cond);
ddekit_simple_free (thread_self->private);
ddekit_simple_free (thread_self->name);
ddekit_simple_free (thread_self);
}
-/* Prepare a wakeup message. */
-static error_t _create_wakeupmsg (struct _ddekit_private_data *data)
-{
- kern_return_t err;
-
- /* Build wakeup message. */
- data->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
- data->wakeupmsg.msgh_size = 0;
-
- err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
- &data->wakeupmsg.msgh_remote_port);
- if (err)
- return EAGAIN;
-
- data->wakeupmsg.msgh_local_port = MACH_PORT_NULL;
- data->wakeupmsg.msgh_seqno = 0;
- data->wakeupmsg.msgh_id = 0;
-
- err = mach_port_insert_right (mach_task_self (),
- data->wakeupmsg.msgh_remote_port,
- data->wakeupmsg.msgh_remote_port,
- MACH_MSG_TYPE_MAKE_SEND);
- if (err) {
- mach_port_destroy (mach_task_self (),
- data->wakeupmsg.msgh_remote_port);
- return EAGAIN;
- }
-
- return 0;
-}
-
static void setup_thread (struct ddekit_thread *t, const char *name) {
- error_t err;
struct _ddekit_private_data *private_data;
if (name) {
@@ -104,14 +65,8 @@ static void setup_thread (struct ddekit_thread *t, const
char *name) {
ddekit_simple_malloc (sizeof (*private_data));
private_data->sleep_cond = ddekit_condvar_init ();
- private_data->list.prev = &private_data->list;
- private_data->list.next = &private_data->list;
private_data->thread = t;
- err = _create_wakeupmsg (private_data);
- if (err)
- error (1, err, "_create_wakeupmsg");
-
t->private = private_data;
}
@@ -267,114 +222,45 @@ void ddekit_init_threads() {
* semaphore
**********************************************************************/
-/* Block THREAD. */
-static error_t _timedblock (struct _ddekit_private_data *data,
- const int timeout)
-{
- error_t err;
- mach_msg_header_t msg;
-
- assert (timeout > 0);
-
- err = mach_msg (&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0,
- sizeof msg, data->wakeupmsg.msgh_remote_port,
- timeout, MACH_PORT_NULL);
- if (err == EMACH_RCV_TIMED_OUT)
- return ETIMEDOUT;
-
- assert_perror (err);
- return 0;
-}
-
-/* Block THREAD. */
-static void _block (struct _ddekit_private_data *data)
+static int _sem_timedwait_internal (ddekit_sem_t *restrict sem, int timeout)
{
- mach_msg_header_t msg;
- error_t err;
-
- err = mach_msg (&msg, MACH_RCV_MSG, 0, sizeof msg,
- data->wakeupmsg.msgh_remote_port,
- MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- assert_perror (err);
-}
-
-static int _sem_timedwait_internal (ddekit_sem_t *restrict sem,
- const int timeout)
-{
- pthread_spin_lock (&sem->lock);
- if (sem->value > 0) {
- /* Successful down. */
- sem->value --;
- pthread_spin_unlock (&sem->lock);
- return 0;
- }
-
- if (timeout < 0) {
- pthread_spin_unlock (&sem->lock);
- errno = EINVAL;
- return -1;
- }
-
- /* Add ourselves to the queue. */
- add_entry_head (&sem->head, &thread_self->private->list);
- pthread_spin_unlock (&sem->lock);
-
- /* Block the thread. */
- if (timeout) {
- error_t err;
-
- err = _timedblock (thread_self->private, timeout);
- if (err) {
- /* We timed out. We may need to disconnect ourself from the
- waiter queue.
-
- FIXME: What do we do if we get a wakeup message before we
- disconnect ourself? It may remain until the next time we
- block. */
- assert (err == ETIMEDOUT);
-
- pthread_spin_lock (&sem->lock);
- remove_entry (&thread_self->private->list);
- pthread_spin_unlock (&sem->lock);
-
- errno = err;
- return -1;
+ int ret;
+ if (timeout)
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ ts.tv_nsec += (timeout%1000) * 1000000;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ts.tv_sec += 1;
}
+ ts.tv_sec += timeout/1000;
+ do
+ ret = sem_timedwait(&sem->sem, &ts);
+ while (ret == -1 && errno == EINTR);
+ return ret;
}
else
- _block (thread_self->private);
-
- return 0;
-}
-
-/* Wakeup THREAD. */
-static void _thread_wakeup (struct _ddekit_private_data *data)
-{
- error_t err;
-
- err = mach_msg (&data->wakeupmsg, MACH_SEND_MSG,
- sizeof (data->wakeupmsg), 0, MACH_PORT_NULL,
- MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
- assert_perror (err);
+ {
+ do
+ ret = sem_wait(&sem->sem);
+ while (ret == -1 && errno == EINTR);
+ return 0;
+ }
}
ddekit_sem_t *ddekit_sem_init(int value) {
ddekit_sem_t *sem =
(ddekit_sem_t *) ddekit_simple_malloc (sizeof (*sem));
- sem->lock = PTHREAD_SPINLOCK_INITIALIZER;
- sem->head.prev = &sem->head;
- sem->head.next = &sem->head;
- sem->value = value;
+ sem_init(&sem->sem, 0, value);
return sem;
}
void ddekit_sem_deinit(ddekit_sem_t *sem) {
- if (!EMPTY_LIST (&sem->head)) {
- error (0, EBUSY, "ddekit_sem_deinit");
- }
- else
- ddekit_simple_free(sem);
+ sem_destroy(&sem->sem);
+ ddekit_simple_free(sem);
}
void ddekit_sem_down(ddekit_sem_t *sem) {
@@ -383,16 +269,7 @@ void ddekit_sem_down(ddekit_sem_t *sem) {
/* returns 0 on success, != 0 when it would block */
int ddekit_sem_down_try(ddekit_sem_t *sem) {
- pthread_spin_lock (&sem->lock);
- if (sem->value > 0) {
- /* Successful down. */
- sem->value --;
- pthread_spin_unlock (&sem->lock);
- return 0;
- }
- pthread_spin_unlock (&sem->lock);
-
- return -1;
+ return sem_trywait(&sem->sem);
}
/* returns 0 on success, != 0 on timeout */
@@ -402,33 +279,6 @@ int ddekit_sem_down_timed(ddekit_sem_t *sem, int timo) {
}
void ddekit_sem_up(ddekit_sem_t *sem) {
- struct _ddekit_private_data *wakeup;
-
- pthread_spin_lock (&sem->lock);
- if (sem->value > 0) {
- /* Do a quick up. */
- assert (EMPTY_LIST (&sem->head));
- sem->value ++;
- pthread_spin_unlock (&sem->lock);
- return;
- }
-
- if (EMPTY_LIST (&sem->head)) {
- /* No one waiting. */
- sem->value = 1;
- pthread_spin_unlock (&sem->lock);
- return;
- }
-
- /* Wake someone up. */
-
- /* First dequeue someone. */
- wakeup = LIST_ENTRY (remove_entry_end (&sem->head),
- struct _ddekit_private_data, list);
-
- /* Then drop the lock and transfer control. */
- pthread_spin_unlock (&sem->lock);
- if (wakeup)
- _thread_wakeup (wakeup);
+ sem_post(&sem->sem);
}
--
Alioth's /usr/local/bin/git-commit-notice on
/srv/git.debian.org/git/pkg-hurd/hurd.git