From a46114ec01e8d174a41744f4f1b49905613847dc Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Mon, 20 Jun 2016 23:49:35 +0200 Subject: lib, irmd, ipcp: robust mutexes Update to POSIX 200112L to allow use of robust mutexes in the shm_du_map. Removed the implementation of the rw_lock in favor of pthread_rwlock_t. Placeholder for the shm_du_map_sanitize function. --- src/lib/CMakeLists.txt | 1 - src/lib/dev.c | 141 ++++++++++++++++++++++++------------------------- src/lib/rw_lock.c | 127 -------------------------------------------- src/lib/shm_du_map.c | 32 ++++++++--- 4 files changed, 95 insertions(+), 206 deletions(-) delete mode 100644 src/lib/rw_lock.c (limited to 'src/lib') diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 7db083b6..ed7f2fc6 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -32,7 +32,6 @@ set(SOURCE_FILES ipcp.c irm.c list.c - rw_lock.c shm_ap_rbuff.c shm_du_map.c sockets.c diff --git a/src/lib/dev.c b/src/lib/dev.c index ab4365b8..1725cca3 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -49,10 +48,10 @@ struct ap_data { struct shm_du_map * dum; struct bmp * fds; struct shm_ap_rbuff * rb; - rw_lock_t data_lock; + pthread_rwlock_t data_lock; struct flow flows[AP_MAX_FLOWS]; - rw_lock_t flows_lock; + pthread_rwlock_t flows_lock; } * _ap_instance; int ap_init(char * ap_name) @@ -109,8 +108,8 @@ int ap_init(char * ap_name) _ap_instance->flows[i].port_id = -1; } - rw_lock_init(&_ap_instance->flows_lock); - rw_lock_init(&_ap_instance->data_lock); + pthread_rwlock_init(&_ap_instance->flows_lock, NULL); + pthread_rwlock_init(&_ap_instance->data_lock, NULL); return 0; } @@ -122,7 +121,7 @@ void ap_fini(void) if (_ap_instance == NULL) return; - rw_lock_wrlock(&_ap_instance->data_lock); + pthread_rwlock_wrlock(&_ap_instance->data_lock); if (_ap_instance->api != NULL) instance_name_destroy(_ap_instance->api); @@ -133,14 +132,14 @@ void ap_fini(void) if (_ap_instance->rb != NULL) shm_ap_rbuff_destroy(_ap_instance->rb); - rw_lock_rdlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->flows_lock); for (i = 0; i < AP_MAX_FLOWS; ++i) if (_ap_instance->flows[i].rb != NULL) shm_ap_rbuff_close(_ap_instance->flows[i].rb); - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); free(_ap_instance); } @@ -166,12 +165,12 @@ int flow_accept(char ** ae_name) msg.code = IRM_MSG_CODE__IRM_FLOW_ACCEPT; msg.has_pid = true; - rw_lock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); msg.ap_name = _ap_instance->api->name; msg.pid = _ap_instance->api->id; - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) { @@ -183,13 +182,13 @@ int flow_accept(char ** ae_name) return -1; } - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_wrlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_wrlock(&_ap_instance->flows_lock); cfd = bmp_allocate(_ap_instance->fds); if (!bmp_is_id_valid(_ap_instance->fds, cfd)) { - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } @@ -197,8 +196,8 @@ int flow_accept(char ** ae_name) _ap_instance->flows[cfd].rb = shm_ap_rbuff_open(recv_msg->pid); if (_ap_instance->flows[cfd].rb == NULL) { bmp_release(_ap_instance->fds, cfd); - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } @@ -208,8 +207,8 @@ int flow_accept(char ** ae_name) if (*ae_name == NULL) { shm_ap_rbuff_close(_ap_instance->flows[cfd].rb); bmp_release(_ap_instance->fds, cfd); - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } @@ -218,8 +217,8 @@ int flow_accept(char ** ae_name) _ap_instance->flows[cfd].port_id = recv_msg->port_id; _ap_instance->flows[cfd].oflags = FLOW_O_DEFAULT; - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); @@ -241,31 +240,31 @@ int flow_alloc_resp(int fd, msg.pid = _ap_instance->api->id; msg.has_port_id = true; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_rdlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->flows_lock); msg.port_id = _ap_instance->flows[fd].port_id; - rw_lock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); msg.has_response = true; msg.response = response; recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } if (!recv_msg->has_result) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } ret = recv_msg->result; - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); @@ -291,11 +290,11 @@ int flow_alloc(char * dst_name, msg.ae_name = src_ae_name; msg.has_pid = true; - rw_lock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); msg.pid = _ap_instance->api->id; - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) { @@ -307,13 +306,13 @@ int flow_alloc(char * dst_name, return -1; } - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_wrlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_wrlock(&_ap_instance->flows_lock); fd = bmp_allocate(_ap_instance->fds); if (!bmp_is_id_valid(_ap_instance->fds, fd)) { - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } @@ -321,8 +320,8 @@ int flow_alloc(char * dst_name, _ap_instance->flows[fd].rb = shm_ap_rbuff_open(recv_msg->pid); if (_ap_instance->flows[fd].rb == NULL) { bmp_release(_ap_instance->fds, fd); - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } @@ -330,8 +329,8 @@ int flow_alloc(char * dst_name, _ap_instance->flows[fd].port_id = recv_msg->port_id; _ap_instance->flows[fd].oflags = FLOW_O_DEFAULT; - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); @@ -350,13 +349,13 @@ int flow_alloc_res(int fd) msg.code = IRM_MSG_CODE__IRM_FLOW_ALLOC_RES; msg.has_port_id = true; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_rdlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->flows_lock); msg.port_id = _ap_instance->flows[fd].port_id; - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) { @@ -384,8 +383,8 @@ int flow_dealloc(int fd) msg.code = IRM_MSG_CODE__IRM_FLOW_DEALLOC; msg.has_port_id = true; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_wrlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_wrlock(&_ap_instance->flows_lock); msg.port_id = _ap_instance->flows[fd].port_id; @@ -395,23 +394,23 @@ int flow_dealloc(int fd) bmp_release(_ap_instance->fds, fd); - rw_lock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); recv_msg = send_recv_irm_msg(&msg); if (recv_msg == NULL) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } if (!recv_msg->has_result) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); return -1; } ret = recv_msg->result; - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); irm_msg__free_unpacked(recv_msg, NULL); @@ -425,24 +424,24 @@ int flow_cntl(int fd, int cmd, int oflags) if (fd < 0) return -EBADF; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_wrlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_wrlock(&_ap_instance->flows_lock); old = _ap_instance->flows[fd].oflags; switch (cmd) { case FLOW_F_GETFL: /* GET FLOW FLAGS */ - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return old; case FLOW_F_SETFL: /* SET FLOW FLAGS */ _ap_instance->flows[fd].oflags = oflags; - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return old; default: - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return FLOW_O_INVALID; /* unknown command */ } } @@ -458,8 +457,8 @@ ssize_t flow_write(int fd, void * buf, size_t count) if (fd < 0) return -EBADF; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_rdlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->flows_lock); if (_ap_instance->flows[fd].oflags & FLOW_O_NONBLOCK) { index = shm_create_du_buff(_ap_instance->dum, @@ -469,8 +468,8 @@ ssize_t flow_write(int fd, void * buf, size_t count) (uint8_t *) buf, count); if (index == -1) { - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } @@ -479,8 +478,8 @@ ssize_t flow_write(int fd, void * buf, size_t count) if (shm_ap_rbuff_write(_ap_instance->flows[fd].rb, &e) < 0) { shm_release_du_buff(_ap_instance->dum, index); - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -EPIPE; } } else { /* blocking */ @@ -499,8 +498,8 @@ ssize_t flow_write(int fd, void * buf, size_t count) ; } - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return 0; } @@ -514,12 +513,12 @@ ssize_t flow_read(int fd, void * buf, size_t count) if (fd < 0) return -EBADF; - rw_lock_rdlock(&_ap_instance->data_lock); - rw_lock_rdlock(&_ap_instance->flows_lock); + pthread_rwlock_rdlock(&_ap_instance->data_lock); + pthread_rwlock_rdlock(&_ap_instance->flows_lock); if (_ap_instance->flows[fd].port_id < 0) { - rw_lock_unlock(&_ap_instance->flows_lock); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } @@ -533,10 +532,10 @@ ssize_t flow_read(int fd, void * buf, size_t count) ; } - rw_lock_unlock(&_ap_instance->flows_lock); + pthread_rwlock_unlock(&_ap_instance->flows_lock); if (idx < 0) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } @@ -544,7 +543,7 @@ ssize_t flow_read(int fd, void * buf, size_t count) _ap_instance->dum, idx); if (n < 0) { - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return -1; } @@ -552,7 +551,7 @@ ssize_t flow_read(int fd, void * buf, size_t count) shm_release_du_buff(_ap_instance->dum, idx); - rw_lock_unlock(&_ap_instance->data_lock); + pthread_rwlock_unlock(&_ap_instance->data_lock); return n; } diff --git a/src/lib/rw_lock.c b/src/lib/rw_lock.c deleted file mode 100644 index ba285694..00000000 --- a/src/lib/rw_lock.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - * - * Read/Write locks - * - * Dimitri Staessens - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -int rw_lock_init(rw_lock_t * lock) -{ - if (lock == NULL) - return -1; - - pthread_mutex_init(&lock->lock, NULL); - pthread_mutex_init(&lock->i_lock, NULL); - lock->i = 0; - - return 0; -} - -void rw_lock_destroy(rw_lock_t * lock) -{ - if (lock == NULL) - return; - - pthread_mutex_destroy(&lock->lock); - pthread_mutex_destroy(&lock->i_lock); - lock->i = -1; -} - -int rw_lock_rdlock(rw_lock_t * lock) -{ - int ret = 0; - - if (lock == NULL) - return -1; - - pthread_mutex_lock(&lock->i_lock); - - if (lock->i < 0) { - pthread_mutex_unlock(&lock->i_lock); - return -1; - } - - if (lock->i == 0) - ret = pthread_mutex_lock(&lock->lock); - - ++(lock->i); - - pthread_mutex_unlock(&lock->i_lock); - - return ret; -} - -int rw_lock_wrlock(rw_lock_t * lock) -{ - int ret = 0; - - if (lock == NULL) - return -1; - - pthread_mutex_lock(&lock->i_lock); - - if (lock->i < 0) { - pthread_mutex_unlock(&lock->i_lock); - return -1; - } - - pthread_mutex_unlock(&lock->i_lock); - - while (1) { - pthread_mutex_lock(&lock->i_lock); - - if (lock->i == 0) { - ++(lock->i); - ret = pthread_mutex_lock(&lock->lock); - pthread_mutex_unlock(&lock->i_lock); - break; - } - - pthread_mutex_unlock(&lock->i_lock); - - sched_yield(); - } - - return ret; -} - -int rw_lock_unlock(rw_lock_t * lock) -{ - int ret = 0; - - if (lock == NULL) - return -1; - - pthread_mutex_lock(&lock->i_lock); - - if (lock->i < 0) { - pthread_mutex_unlock(&lock->i_lock); - return -1; - } - - --(lock->i); - - if (lock->i == 0) - ret = pthread_mutex_unlock(&lock->lock); - - pthread_mutex_unlock(&lock->i_lock); - - return ret; -} diff --git a/src/lib/shm_du_map.c b/src/lib/shm_du_map.c index 5f935d3f..f5909e11 100644 --- a/src/lib/shm_du_map.c +++ b/src/lib/shm_du_map.c @@ -36,7 +36,8 @@ #define SHM_BLOCKS_SIZE (SHM_BLOCKS_IN_MAP * SHM_DU_BUFF_BLOCK_SIZE) #define SHM_FILE_SIZE (SHM_BLOCKS_SIZE + 2 * sizeof (size_t) \ - + sizeof(pthread_mutex_t)) + sizeof(pid_t) + + sizeof(pthread_mutex_t) + sizeof(pthread_cond_t) \ + + sizeof(pid_t)) #define get_head_ptr(dum) \ ((struct shm_du_buff *)(dum->shm_base + (*dum->ptr_head * \ @@ -73,6 +74,7 @@ struct shm_du_map { size_t * ptr_head; /* start of ringbuffer head */ size_t * ptr_tail; /* start of ringbuffer tail */ pthread_mutex_t * shm_mutex; /* lock all free space in shm */ + pthread_cond_t * sanitize; /* run sanitizer when buffer full */ pid_t * pid; /* pid of the irmd owner */ int fd; }; @@ -82,7 +84,8 @@ struct shm_du_map * shm_du_map_create() struct shm_du_map * dum; int shm_fd; uint8_t * shm_base; - pthread_mutexattr_t attr; + pthread_mutexattr_t mattr; + pthread_condattr_t cattr; dum = malloc(sizeof *dum); if (dum == NULL) { @@ -137,11 +140,17 @@ struct shm_du_map * shm_du_map_create() ((uint8_t *) dum->shm_base + SHM_BLOCKS_SIZE); dum->ptr_tail = dum->ptr_head + 1; dum->shm_mutex = (pthread_mutex_t *) (dum->ptr_tail + 1); - dum->pid = (pid_t *) (dum->shm_mutex + 1); + dum->sanitize = (pthread_cond_t *) (dum->shm_mutex + 1); + dum->pid = (pid_t *) (dum->sanitize + 1); - pthread_mutexattr_init(&attr); - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - pthread_mutex_init(dum->shm_mutex, &attr); + pthread_mutexattr_init(&mattr); + pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); + pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); + pthread_mutex_init(dum->shm_mutex, &mattr); + + pthread_condattr_init(&cattr); + pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); + pthread_cond_init(dum->sanitize, &cattr); *dum->ptr_head = 0; *dum->ptr_tail = 0; @@ -193,7 +202,8 @@ struct shm_du_map * shm_du_map_open() ((uint8_t *) dum->shm_base + SHM_BLOCKS_SIZE); dum->ptr_tail = dum->ptr_head + 1; dum->shm_mutex = (pthread_mutex_t *) (dum->ptr_tail + 1); - dum->pid = (pid_t *) (dum->shm_mutex + 1); + dum->sanitize = (pthread_cond_t *) (dum->shm_mutex + 1); + dum->pid = (pid_t *) (dum->sanitize + 1); dum->fd = shm_fd; @@ -205,6 +215,12 @@ pid_t shm_du_map_owner(struct shm_du_map * dum) return *dum->pid; } +void * shm_du_map_sanitize(void * o) +{ + LOG_MISSING; + return (void *) 0; +} + void shm_du_map_close(struct shm_du_map * dum) { if (dum == NULL) { @@ -294,11 +310,13 @@ ssize_t shm_create_du_buff(struct shm_du_map * dum, if (!shm_map_free(dum, blocks)) { pthread_mutex_unlock(dum->shm_mutex); + pthread_cond_signal(dum->sanitize); return -1; } #else if (!shm_map_free(dum, 1)) { pthread_mutex_unlock(dum->shm_mutex); + ptrhead_cond_signal(dum->sanitize); return -1; } #endif -- cgit v1.2.3