From: Libor Peltan Date: Tue, 2 Apr 2019 15:46:37 +0000 (+0200) Subject: semaphore: custom implementation to somehow work on OpenBSD and OSX X-Git-Tag: v2.9.0~286^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc7f4f82fb88756146b1bc8e62d17fd5a2a5ae65;p=thirdparty%2Fknot-dns.git semaphore: custom implementation to somehow work on OpenBSD and OSX --- diff --git a/Knot.files b/Knot.files index ef099e81ee..bb93e4d13d 100644 --- a/Knot.files +++ b/Knot.files @@ -37,6 +37,8 @@ src/contrib/openbsd/strlcpy.c src/contrib/openbsd/strlcpy.h src/contrib/qp-trie/trie.c src/contrib/qp-trie/trie.h +src/contrib/semaphore.c +src/contrib/semaphore.h src/contrib/sockaddr.c src/contrib/sockaddr.h src/contrib/string.c diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc index cef7e0b8cc..f018760897 100644 --- a/src/contrib/Makefile.inc +++ b/src/contrib/Makefile.inc @@ -36,6 +36,8 @@ libcontrib_la_SOURCES = \ contrib/net.h \ contrib/qp-trie/trie.c \ contrib/qp-trie/trie.h \ + contrib/semaphore.c \ + contrib/semaphore.h \ contrib/sockaddr.c \ contrib/sockaddr.h \ contrib/string.c \ diff --git a/src/contrib/semaphore.c b/src/contrib/semaphore.c new file mode 100644 index 0000000000..724443db1c --- /dev/null +++ b/src/contrib/semaphore.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2019 CZ.NIC, z.s.p.o. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "semaphore.h" + +#include + +void knot_sem_init(knot_sem_t *sem, unsigned int value) +{ + int ret = sem_init(&sem->semaphore, 1, value); + if (ret == 0) { + sem->status = -1; + } else { + sem->status = value; + sem->status_lock = malloc(sizeof(*sem->status_lock)); + pthread_mutex_init(&sem->status_lock->mutex, NULL); + pthread_cond_init(&sem->status_lock->cond, NULL); + } +} + +void knot_sem_wait(knot_sem_t *sem) +{ + if (sem->status < 0) { + sem_wait(&sem->semaphore); + } else { + pthread_mutex_lock(&sem->status_lock->mutex); + while (sem->status == 0) { + pthread_cond_wait(&sem->status_lock->cond, &sem->status_lock->mutex); + } + sem->status--; + pthread_mutex_unlock(&sem->status_lock->mutex); + } +} + +void knot_sem_post(knot_sem_t *sem) +{ + if (sem->status < 0) { + sem_post(&sem->semaphore); + } else { + pthread_mutex_lock(&sem->status_lock->mutex); + sem->status++; + pthread_cond_signal(&sem->status_lock->cond); + pthread_mutex_unlock(&sem->status_lock->mutex); + } +} + +void knot_sem_destroy(knot_sem_t *sem) +{ + knot_sem_wait(sem); + if (sem->status < 0) { + sem_destroy(&sem->semaphore); + } else { + pthread_cond_destroy(&sem->status_lock->cond); + pthread_mutex_destroy(&sem->status_lock->mutex); + free(sem->status_lock); + } +} diff --git a/src/contrib/semaphore.h b/src/contrib/semaphore.h new file mode 100644 index 0000000000..be49b7fe26 --- /dev/null +++ b/src/contrib/semaphore.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2019 CZ.NIC, z.s.p.o. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include + +#pragma once + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; +} knot_sem_mutex_t; + +typedef struct { + int status; + union { + sem_t semaphore; + knot_sem_mutex_t *status_lock; + }; +} knot_sem_t; + +void knot_sem_init(knot_sem_t *sem, unsigned int value); + +void knot_sem_wait(knot_sem_t *sem); + +void knot_sem_post(knot_sem_t *sem); + +void knot_sem_destroy(knot_sem_t *sem); diff --git a/src/knot/updates/apply.c b/src/knot/updates/apply.c index 11910d08f7..dc119909dd 100644 --- a/src/knot/updates/apply.c +++ b/src/knot/updates/apply.c @@ -420,7 +420,7 @@ void update_cleanup(apply_ctx_t *ctx) zone_trees_unify_binodes(ctx->contents->nodes, ctx->contents->nsec3_nodes); if (ctx->cow_mutex != NULL) { - sem_post(ctx->cow_mutex); + knot_sem_post(ctx->cow_mutex); } } @@ -449,7 +449,7 @@ void update_rollback(apply_ctx_t *ctx) } if (ctx->cow_mutex != NULL) { - sem_post(ctx->cow_mutex); + knot_sem_post(ctx->cow_mutex); } free(ctx->contents->nodes); diff --git a/src/knot/updates/apply.h b/src/knot/updates/apply.h index 113db49800..d307e6681d 100644 --- a/src/knot/updates/apply.h +++ b/src/knot/updates/apply.h @@ -16,8 +16,7 @@ #pragma once -#include - +#include "contrib/semaphore.h" #include "knot/zone/contents.h" #include "knot/updates/changesets.h" #include "contrib/ucw/lists.h" @@ -31,7 +30,7 @@ struct apply_ctx { zone_tree_t *node_ptrs; /*!< Just pointers to the affected nodes in contents. */ zone_tree_t *nsec3_ptrs; /*!< The same for NSEC3 nodes. */ uint32_t flags; - sem_t *cow_mutex; // pointer to zone_t struct + knot_sem_t *cow_mutex; }; typedef struct apply_ctx apply_ctx_t; diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c index b9ae86f893..aa98907b04 100644 --- a/src/knot/updates/zone-update.c +++ b/src/knot/updates/zone-update.c @@ -127,7 +127,7 @@ int init_base(zone_update_t *update, zone_t *zone, zone_contents_t *old_contents return KNOT_ENOMEM; } - sem_wait(&zone->cow_lock); + knot_sem_wait(&zone->cow_lock); update->a_ctx->cow_mutex = &zone->cow_lock; int ret = KNOT_EINVAL; @@ -137,7 +137,7 @@ int init_base(zone_update_t *update, zone_t *zone, zone_contents_t *old_contents ret = init_full(update, zone); } if (ret != KNOT_EOK) { - sem_post(&zone->cow_lock); + knot_sem_post(&zone->cow_lock); free(update->a_ctx); } @@ -221,7 +221,7 @@ int zone_update_from_contents(zone_update_t *update, zone_t *zone_without_conten return KNOT_ENOMEM; } - sem_wait(&update->zone->cow_lock); + knot_sem_wait(&update->zone->cow_lock); update->a_ctx->cow_mutex = &update->zone->cow_lock; if (flags & UPDATE_INCREMENTAL) { @@ -343,7 +343,7 @@ void zone_update_clear(zone_update_t *update) zone_contents_deep_free(update->new_cont); } if (update->a_ctx != NULL && update->a_ctx->cow_mutex != NULL) { - sem_post(update->a_ctx->cow_mutex); + knot_sem_post(update->a_ctx->cow_mutex); } free(update->a_ctx); mp_delete(update->mm.ctx); diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index de97d4db2b..1e8e404498 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -175,7 +175,7 @@ zone_t* zone_new(const knot_dname_t *name) zone->ddns_queue_size = 0; init_list(&zone->ddns_queue); - sem_init(&zone->cow_lock, 1, 1); + knot_sem_init(&zone->cow_lock, 1); // Preferred master lock pthread_mutex_init(&zone->preferred_lock, NULL); @@ -215,8 +215,7 @@ void zone_free(zone_t **zone_ptr) free_ddns_queue(zone); pthread_mutex_destroy(&zone->ddns_lock); - sem_wait(&zone->cow_lock); - sem_destroy(&zone->cow_lock); + knot_sem_destroy(&zone->cow_lock); /* Control update. */ zone_control_clear(zone); diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h index e4841c2c5c..440fe2f134 100644 --- a/src/knot/zone/zone.h +++ b/src/knot/zone/zone.h @@ -16,8 +16,7 @@ #pragma once -#include - +#include "contrib/semaphore.h" #include "knot/conf/conf.h" #include "knot/conf/confio.h" #include "knot/journal/journal_basic.h" @@ -74,7 +73,7 @@ typedef struct zone struct zone_update *control_update; /*! \brief Ensue one COW tramsaction on zone's trees at a time. */ - sem_t cow_lock; + knot_sem_t cow_lock; /*! \brief Ptr to journal DB (in struct server) */ knot_lmdb_db_t *journaldb; diff --git a/tests/knot/test_zone-update.c b/tests/knot/test_zone-update.c index 61fbf768df..288a11ca65 100644 --- a/tests/knot/test_zone-update.c +++ b/tests/knot/test_zone-update.c @@ -108,9 +108,9 @@ static int test_node_unified(zone_node_t *n1, void *v) static void test_zone_unified(zone_t *z) { - sem_wait(&z->cow_lock); + knot_sem_wait(&z->cow_lock); zone_tree_apply(z->contents->nodes, test_node_unified, NULL); - sem_post(&z->cow_lock); + knot_sem_post(&z->cow_lock); } void test_full(zone_t *zone, zs_scanner_t *sc)