root/opal/mca/pmix/pmix4x/pmix/src/mca/gds/ds12/gds_ds12_lock_pthread.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pmix_gds_ds12_lock_init
  2. pmix_ds12_lock_finalize
  3. pmix_ds12_lock_rd_get
  4. pmix_ds12_lock_wr_get
  5. pmix_ds12_lock_rw_rel

   1 /*
   2  * Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
   3  * Copyright (c) 2016      IBM Corporation.  All rights reserved.
   4  * Copyright (c) 2016-2018 Mellanox Technologies, Inc.
   5  *                         All rights reserved.
   6  * Copyright (c) 2018      Research Organization for Information Science
   7  *                         and Technology (RIST).  All rights reserved.
   8  *
   9  * $COPYRIGHT$
  10  *
  11  * Additional copyrights may follow
  12  *
  13  * $HEADER$
  14  */
  15 
  16 #include <src/include/pmix_config.h>
  17 
  18 #include <stdio.h>
  19 #ifdef HAVE_UNISTD_H
  20 #include <unistd.h>
  21 #endif
  22 #ifdef HAVE_SYS_TYPES_H
  23 #include <sys/types.h>
  24 #endif
  25 #ifdef HAVE_SYS_STAT_H
  26 #include <sys/stat.h>
  27 #endif
  28 
  29 #include <pmix_common.h>
  30 
  31 #include "src/mca/common/dstore/dstore_common.h"
  32 #include "src/mca/gds/base/base.h"
  33 #include "src/mca/pshmem/pshmem.h"
  34 
  35 #include "src/util/error.h"
  36 #include "src/util/output.h"
  37 
  38 #include "gds_ds12_lock.h"
  39 #include "src/mca/common/dstore/dstore_segment.h"
  40 
  41 #define _ESH_12_PTHREAD_LOCK(rwlock, func)                  \
  42 __pmix_attribute_extension__ ({                             \
  43     pmix_status_t ret = PMIX_SUCCESS;                       \
  44     int rc;                                                 \
  45     rc = pthread_rwlock_##func(rwlock);                     \
  46     if (0 != rc) {                                          \
  47         switch (errno) {                                    \
  48             case EINVAL:                                    \
  49                 ret = PMIX_ERR_INIT;                        \
  50                 break;                                      \
  51             case EPERM:                                     \
  52                 ret = PMIX_ERR_NO_PERMISSIONS;              \
  53                 break;                                      \
  54         }                                                   \
  55     }                                                       \
  56     if (ret) {                                              \
  57         pmix_output(0, "%s %d:%s lock failed: %s",          \
  58             __FILE__, __LINE__, __func__, strerror(errno)); \
  59     }                                                       \
  60     ret;                                                    \
  61 })
  62 
  63 typedef struct {
  64     char *lockfile;
  65     pmix_pshmem_seg_t *segment;
  66     pthread_rwlock_t *rwlock;
  67 } ds12_lock_pthread_ctx_t;
  68 
  69 pmix_status_t pmix_gds_ds12_lock_init(pmix_common_dstor_lock_ctx_t *ctx, const char *base_path,
  70                                       const char * name, uint32_t local_size, uid_t uid, bool setuid)
  71 {
  72     size_t size = pmix_common_dstor_getpagesize();
  73     pmix_status_t rc = PMIX_SUCCESS;
  74     pthread_rwlockattr_t attr;
  75     ds12_lock_pthread_ctx_t *lock_ctx = (ds12_lock_pthread_ctx_t*)ctx;
  76 
  77     if (*ctx != NULL) {
  78         return PMIX_SUCCESS;
  79     }
  80 
  81     lock_ctx = (ds12_lock_pthread_ctx_t*)malloc(sizeof(ds12_lock_pthread_ctx_t));
  82     if (NULL == lock_ctx) {
  83         rc = PMIX_ERR_INIT;
  84         PMIX_ERROR_LOG(rc);
  85         goto error;
  86     }
  87     memset(lock_ctx, 0, sizeof(ds12_lock_pthread_ctx_t));
  88     *ctx = (pmix_common_dstor_lock_ctx_t*)lock_ctx;
  89 
  90     lock_ctx->segment = (pmix_pshmem_seg_t *)malloc(sizeof(pmix_pshmem_seg_t));
  91     if (NULL == lock_ctx->segment) {
  92         rc = PMIX_ERR_OUT_OF_RESOURCE;
  93         PMIX_ERROR_LOG(rc);
  94         goto error;
  95     }
  96 
  97     /* create a lock file to prevent clients from reading while server is writing
  98      * to the shared memory. This situation is quite often, especially in case of
  99      * direct modex when clients might ask for data simultaneously. */
 100     if(0 > asprintf(&lock_ctx->lockfile, "%s/dstore_sm.lock", base_path)) {
 101         rc = PMIX_ERR_OUT_OF_RESOURCE;
 102         PMIX_ERROR_LOG(rc);
 103         goto error;
 104     }
 105     PMIX_OUTPUT_VERBOSE((10, pmix_gds_base_framework.framework_output,
 106         "%s:%d:%s _lockfile_name: %s", __FILE__, __LINE__, __func__, lock_ctx->lockfile));
 107 
 108     if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) {
 109         if (PMIX_SUCCESS != (rc = pmix_pshmem.segment_create(lock_ctx->segment,
 110                                             lock_ctx->lockfile, size))) {
 111             PMIX_ERROR_LOG(rc);
 112             goto error;
 113         }
 114         memset(lock_ctx->segment->seg_base_addr, 0, size);
 115         if (0 != setuid) {
 116             if (0 > chown(lock_ctx->lockfile, (uid_t) uid, (gid_t) -1)){
 117                 rc = PMIX_ERROR;
 118                 PMIX_ERROR_LOG(rc);
 119                 goto error;
 120             }
 121             /* set the mode as required */
 122             if (0 > chmod(lock_ctx->lockfile, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP )) {
 123                 rc = PMIX_ERROR;
 124                 PMIX_ERROR_LOG(rc);
 125                 goto error;
 126             }
 127         }
 128         lock_ctx->rwlock = (pthread_rwlock_t *)lock_ctx->segment->seg_base_addr;
 129 
 130         if (0 != pthread_rwlockattr_init(&attr)) {
 131             rc = PMIX_ERROR;
 132             PMIX_ERROR_LOG(rc);
 133             goto error;
 134         }
 135         if (0 != pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
 136             pthread_rwlockattr_destroy(&attr);
 137             rc = PMIX_ERR_INIT;
 138             PMIX_ERROR_LOG(rc);
 139             goto error;
 140         }
 141 #ifdef HAVE_PTHREAD_SETKIND
 142         if (0 != pthread_rwlockattr_setkind_np(&attr,
 143                                 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) {
 144             pthread_rwlockattr_destroy(&attr);
 145             PMIX_ERROR_LOG(PMIX_ERR_INIT);
 146             goto error;
 147         }
 148 #endif
 149         if (0 != pthread_rwlock_init(lock_ctx->rwlock, &attr)) {
 150             pthread_rwlockattr_destroy(&attr);
 151             PMIX_ERROR_LOG(PMIX_ERR_INIT);
 152             goto error;
 153         }
 154         if (0 != pthread_rwlockattr_destroy(&attr)) {
 155             PMIX_ERROR_LOG(PMIX_ERR_INIT);
 156             goto error;
 157         }
 158 
 159     }
 160     else {
 161         lock_ctx->segment->seg_size = size;
 162         snprintf(lock_ctx->segment->seg_name, PMIX_PATH_MAX, "%s", lock_ctx->lockfile);
 163         if (PMIX_SUCCESS != (rc = pmix_pshmem.segment_attach(lock_ctx->segment,
 164                                                              PMIX_PSHMEM_RW))) {
 165             PMIX_ERROR_LOG(rc);
 166             goto error;
 167         }
 168         lock_ctx->rwlock = (pthread_rwlock_t *)lock_ctx->segment->seg_base_addr;
 169     }
 170 
 171     return PMIX_SUCCESS;
 172 
 173 error:
 174     if (NULL != lock_ctx) {
 175         if (lock_ctx->segment) {
 176             /* detach & unlink from current desc */
 177             if (lock_ctx->segment->seg_cpid == getpid()) {
 178                 pmix_pshmem.segment_unlink(lock_ctx->segment);
 179             }
 180             pmix_pshmem.segment_detach(lock_ctx->segment);
 181             lock_ctx->rwlock = NULL;
 182         }
 183         if (NULL != lock_ctx->lockfile) {
 184             free(lock_ctx->lockfile);
 185         }
 186         free(lock_ctx);
 187         *ctx = (pmix_common_dstor_lock_ctx_t*)NULL;
 188     }
 189 
 190     return rc;
 191 }
 192 
 193 void pmix_ds12_lock_finalize(pmix_common_dstor_lock_ctx_t *lock_ctx)
 194 {
 195     ds12_lock_pthread_ctx_t *pthread_lock =
 196             (ds12_lock_pthread_ctx_t*)*lock_ctx;
 197 
 198     if (NULL == pthread_lock) {
 199         PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND);
 200         return;
 201     }
 202     if (0 != pthread_rwlock_destroy(pthread_lock->rwlock)) {
 203         PMIX_ERROR_LOG(PMIX_ERROR);
 204         return;
 205     }
 206 
 207     if (NULL == pthread_lock->segment) {
 208         PMIX_ERROR_LOG(PMIX_ERROR);
 209         return;
 210     }
 211     if (NULL == pthread_lock->lockfile) {
 212         PMIX_ERROR_LOG(PMIX_ERROR);
 213         return;
 214     }
 215 
 216     /* detach & unlink from current desc */
 217     if (pthread_lock->segment->seg_cpid == getpid()) {
 218         pmix_pshmem.segment_unlink(pthread_lock->segment);
 219     }
 220     pmix_pshmem.segment_detach(pthread_lock->segment);
 221 
 222     free(pthread_lock->segment);
 223     pthread_lock->segment = NULL;
 224     free(pthread_lock->lockfile);
 225     pthread_lock->lockfile = NULL;
 226     pthread_lock->rwlock = NULL;
 227     free(pthread_lock);
 228     *lock_ctx = NULL;
 229 }
 230 
 231 pmix_status_t pmix_ds12_lock_rd_get(pmix_common_dstor_lock_ctx_t lock_ctx)
 232 {
 233     ds12_lock_pthread_ctx_t *pthread_lock = (ds12_lock_pthread_ctx_t*)lock_ctx;
 234     pmix_status_t rc;
 235 
 236     if (NULL == pthread_lock) {
 237         rc = PMIX_ERR_NOT_FOUND;
 238         PMIX_ERROR_LOG(rc);
 239         return rc;
 240     }
 241     rc = _ESH_12_PTHREAD_LOCK(pthread_lock->rwlock, rdlock);
 242 
 243     return rc;
 244 }
 245 
 246 pmix_status_t pmix_ds12_lock_wr_get(pmix_common_dstor_lock_ctx_t lock_ctx)
 247 {
 248     ds12_lock_pthread_ctx_t *pthread_lock = (ds12_lock_pthread_ctx_t*)lock_ctx;
 249     pmix_status_t rc;
 250 
 251     if (NULL == pthread_lock) {
 252         rc = PMIX_ERR_NOT_FOUND;
 253         PMIX_ERROR_LOG(rc);
 254         return rc;
 255     }
 256     rc = _ESH_12_PTHREAD_LOCK(pthread_lock->rwlock, wrlock);
 257 
 258     return rc;
 259 }
 260 
 261 pmix_status_t pmix_ds12_lock_rw_rel(pmix_common_dstor_lock_ctx_t lock_ctx)
 262 {
 263     ds12_lock_pthread_ctx_t *pthread_lock = (ds12_lock_pthread_ctx_t*)lock_ctx;
 264     pmix_status_t rc;
 265 
 266     if (NULL == pthread_lock) {
 267         rc = PMIX_ERR_NOT_FOUND;
 268         PMIX_ERROR_LOG(rc);
 269         return rc;
 270     }
 271     rc = _ESH_12_PTHREAD_LOCK(pthread_lock->rwlock, unlock);
 272 
 273     return rc;
 274 }

/* [<][>][^][v][top][bottom][index][help] */