This patch adds pthread read write locks.
This implementation is ported by referring os test in latest nuttx.
Change-Id: I7f01845f36eb931405ca27f3b3b54cd9599a2e93
Signed-off-by: Vidisha Thapa <thapa.v@samsung.com>
CSRCS += pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c
CSRCS += pthread_setcancelstate.c pthread_setcanceltype.c
CSRCS += pthread_testcancel.c
+CSRCS += pthread_rwlock.c pthread_rwlock_rdlock.c pthread_rwlock_wrlock.c
ifeq ($(CONFIG_ENABLE_IOTIVITY),y)
CSRCS += pthread_condattrsetclock.c
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * lib/libc/pthread/pthread_rwlock.c
+ *
+ * Copyright (C) 2017 Mark Schulte. All rights reserved.
+ * Author: Mark Schulte <mark@mjs.pw>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <tinyara/semaphore.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int pthread_rwlock_init(FAR pthread_rwlock_t *lock, FAR const pthread_rwlockattr_t *attr)
+{
+ int err;
+
+ if (attr != NULL) {
+ return -ENOSYS;
+ }
+
+ lock->num_readers = 0;
+ lock->num_writers = 0;
+ lock->write_in_progress = false;
+
+ err = pthread_cond_init(&lock->cv, NULL);
+ if (err != 0) {
+ return err;
+ }
+
+ err = pthread_mutex_init(&lock->lock, NULL);
+ if (err != 0) {
+ pthread_cond_destroy(&lock->cv);
+ return err;
+ }
+
+ return err;
+}
+
+int pthread_rwlock_destroy(FAR pthread_rwlock_t *lock)
+{
+ int cond_err = pthread_cond_destroy(&lock->cv);
+ int mutex_err = pthread_mutex_destroy(&lock->lock);
+
+ if (mutex_err) {
+ return mutex_err;
+ }
+
+ return cond_err;
+}
+
+int pthread_rwlock_unlock(FAR pthread_rwlock_t *rw_lock)
+{
+ int err;
+
+ err = pthread_mutex_lock(&rw_lock->lock);
+ if (err != 0) {
+ return err;
+ }
+
+ if (rw_lock->num_readers > 0) {
+ rw_lock->num_readers--;
+
+ if (rw_lock->num_readers == 0) {
+ err = pthread_cond_broadcast(&rw_lock->cv);
+ }
+ } else if (rw_lock->write_in_progress) {
+ rw_lock->write_in_progress = false;
+
+ err = pthread_cond_broadcast(&rw_lock->cv);
+ } else {
+ err = EINVAL;
+ }
+
+ pthread_mutex_unlock(&rw_lock->lock);
+ return err;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * lib/libc/pthread/pthread_rwlock_rdlock.c
+ *
+ * Copyright (C) 2017 Mark Schulte. All rights reserved.
+ * Author: Mark Schulte <mark@mjs.pw>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <tinyara/semaphore.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_PTHREAD_CLEANUP
+static void rdlock_cleanup(FAR void *arg)
+{
+ FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *) arg;
+
+ (void)pthread_mutex_unlock(&rw_lock->lock);
+}
+#endif
+
+static int tryrdlock(FAR pthread_rwlock_t *rw_lock)
+{
+ int err;
+
+ if (rw_lock->num_writers > 0 || rw_lock->write_in_progress) {
+ err = EBUSY;
+ } else if (rw_lock->num_readers == UINT_MAX) {
+ err = EAGAIN;
+ } else {
+ rw_lock->num_readers++;
+ err = OK;
+ }
+
+ return err;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_rwlock_rdlock
+ *
+ * Description:
+ * Locks a read/write lock for reading
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *rw_lock)
+{
+ int err = pthread_mutex_trylock(&rw_lock->lock);
+
+ if (err != 0) {
+ return err;
+ }
+
+ err = tryrdlock(rw_lock);
+
+ pthread_mutex_unlock(&rw_lock->lock);
+ return err;
+}
+
+int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *rw_lock, FAR const struct timespec *ts)
+{
+ int err = pthread_mutex_lock(&rw_lock->lock);
+
+ if (err != 0) {
+ return err;
+ }
+#ifdef CONFIG_PTHREAD_CLEANUP
+ pthread_cleanup_push(&rdlock_cleanup, rw_lock);
+#endif
+ while ((err = tryrdlock(rw_lock)) == EBUSY) {
+ if (ts != NULL) {
+ err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
+ } else {
+ err = pthread_cond_wait(&rw_lock->cv, &rw_lock->lock);
+ }
+
+ if (err != 0) {
+ break;
+ }
+ }
+#ifdef CONFIG_PTHREAD_CLEANUP
+ pthread_cleanup_pop(0);
+#endif
+
+ pthread_mutex_unlock(&rw_lock->lock);
+ return err;
+}
+
+int pthread_rwlock_rdlock(FAR pthread_rwlock_t *rw_lock)
+{
+ return pthread_rwlock_timedrdlock(rw_lock, NULL);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * lib/libc/pthread/pthread_rwlock_wrlock.c
+ *
+ * Copyright (C) 2017 Mark Schulte. All rights reserved.
+ * Author: Mark Schulte <mark@mjs.pw>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <tinyara/config.h>
+
+#include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <tinyara/semaphore.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_PTHREAD_CLEANUP
+static void wrlock_cleanup(FAR void *arg)
+{
+ FAR pthread_rwlock_t *rw_lock = (FAR pthread_rwlock_t *) arg;
+
+ rw_lock->num_writers--;
+ (void)pthread_mutex_unlock(&rw_lock->lock);
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_rwlock_wrlock
+ *
+ * Description:
+ * Locks a read/write lock for writing
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *rw_lock)
+{
+ int err = pthread_mutex_trylock(&rw_lock->lock);
+
+ if (err != 0) {
+ return err;
+ }
+
+ if (rw_lock->num_readers > 0 || rw_lock->write_in_progress) {
+ err = EBUSY;
+ } else {
+ rw_lock->write_in_progress = true;
+ }
+
+ pthread_mutex_unlock(&rw_lock->lock);
+ return err;
+}
+
+int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock, FAR const struct timespec *ts)
+{
+ int err = pthread_mutex_lock(&rw_lock->lock);
+
+ if (err != 0) {
+ return err;
+ }
+
+ if (rw_lock->num_writers == UINT_MAX) {
+ err = EAGAIN;
+ goto exit_with_mutex;
+ }
+
+ rw_lock->num_writers++;
+
+#ifdef CONFIG_PTHREAD_CLEANUP
+ pthread_cleanup_push(&wrlock_cleanup, rw_lock);
+#endif
+ while (rw_lock->write_in_progress || rw_lock->num_readers > 0) {
+ if (ts != NULL) {
+ err = pthread_cond_timedwait(&rw_lock->cv, &rw_lock->lock, ts);
+ } else {
+ err = pthread_cond_wait(&rw_lock->cv, &rw_lock->lock);
+ }
+
+ if (err != 0) {
+ break;
+ }
+ }
+#ifdef CONFIG_PTHREAD_CLEANUP
+ pthread_cleanup_pop(0);
+#endif
+
+ if (err == 0) {
+ rw_lock->write_in_progress = true;
+ } else {
+ /* In case of error, notify any blocked readers. */
+
+ (void)pthread_cond_broadcast(&rw_lock->cv);
+ }
+
+ rw_lock->num_writers--;
+
+exit_with_mutex:
+ pthread_mutex_unlock(&rw_lock->lock);
+ return err;
+}
+
+int pthread_rwlock_wrlock(FAR pthread_rwlock_t *rw_lock)
+{
+ return pthread_rwlock_timedwrlock(rw_lock, NULL);
+}
typedef CODE void (*pthread_cleanup_t)(FAR void *arg);
#endif
+struct pthread_rwlock_s {
+ pthread_mutex_t lock;
+ pthread_cond_t cv;
+ unsigned int num_readers;
+ unsigned int num_writers;
+ bool write_in_progress;
+};
+
+typedef struct pthread_rwlock_s pthread_rwlock_t;
+
+typedef int pthread_rwlockattr_t;
+
+#define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, \
+ PTHREAD_COND_INITIALIZER, \
+ 0, 0, false}
+
/* Forware references */
struct sched_param; /* Defined in sched.h */
*/
int pthread_setcancelstate(int state, FAR int *oldstate);
-int pthread_setcanceltype(int type, FAR int *oldtype);
+int pthread_setcanceltype(int type, FAR int *oldtype);
/**
* @cond
/**
* @} *///end for PTHREAD_KERNEL
+/* Pthread rwlock */
+
+int pthread_rwlock_destroy(FAR pthread_rwlock_t *rw_lock);
+int pthread_rwlock_init(FAR pthread_rwlock_t *rw_lock, FAR const pthread_rwlockattr_t *attr);
+int pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+int pthread_rwlock_timedrdlock(FAR pthread_rwlock_t *lock, FAR const struct timespec *abstime);
+int pthread_rwlock_tryrdlock(FAR pthread_rwlock_t *lock);
+int pthread_rwlock_wrlock(FAR pthread_rwlock_t *lock);
+int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *lock, FAR const struct timespec *abstime);
+int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *lock);
+int pthread_rwlock_unlock(FAR pthread_rwlock_t *lock);
+
#ifdef __cplusplus
}
#endif