1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#include "apr.h" 18251875Speter#include "apr_strings.h" 19251875Speter#include "apr_arch_proc_mutex.h" 20251875Speter#include "apr_arch_file_io.h" /* for apr_mkstemp() */ 21251875Speter#include "apr_hash.h" 22362181Sdim#include "apr_atomic.h" 23251875Speter 24251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) 25251875Speter{ 26251875Speter return apr_pool_cleanup_run(mutex->pool, mutex, apr_proc_mutex_cleanup); 27251875Speter} 28251875Speter 29251875Speter#if APR_HAS_POSIXSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || \ 30362181Sdim APR_HAS_SYSVSEM_SERIALIZE 31251875Speterstatic apr_status_t proc_mutex_no_child_init(apr_proc_mutex_t **mutex, 32251875Speter apr_pool_t *cont, 33251875Speter const char *fname) 34251875Speter{ 35251875Speter return APR_SUCCESS; 36251875Speter} 37251875Speter#endif 38251875Speter 39362181Sdim#if APR_HAS_POSIXSEM_SERIALIZE || APR_HAS_PROC_PTHREAD_SERIALIZE 40362181Sdimstatic apr_status_t proc_mutex_no_perms_set(apr_proc_mutex_t *mutex, 41362181Sdim apr_fileperms_t perms, 42362181Sdim apr_uid_t uid, 43362181Sdim apr_gid_t gid) 44362181Sdim{ 45362181Sdim return APR_ENOTIMPL; 46362181Sdim} 47362181Sdim#endif 48362181Sdim 49362181Sdim#if APR_HAS_FCNTL_SERIALIZE \ 50362181Sdim || APR_HAS_FLOCK_SERIALIZE \ 51362181Sdim || (APR_HAS_SYSVSEM_SERIALIZE \ 52362181Sdim && !defined(HAVE_SEMTIMEDOP)) \ 53362181Sdim || (APR_HAS_POSIXSEM_SERIALIZE \ 54362181Sdim && !defined(HAVE_SEM_TIMEDWAIT)) \ 55362181Sdim || (APR_HAS_PROC_PTHREAD_SERIALIZE \ 56362181Sdim && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) \ 57362181Sdim && !defined(HAVE_PTHREAD_CONDATTR_SETPSHARED)) 58362181Sdimstatic apr_status_t proc_mutex_spinsleep_timedacquire(apr_proc_mutex_t *mutex, 59362181Sdim apr_interval_time_t timeout) 60362181Sdim{ 61362181Sdim#define SLEEP_TIME apr_time_from_msec(10) 62362181Sdim apr_status_t rv; 63362181Sdim for (;;) { 64362181Sdim rv = apr_proc_mutex_trylock(mutex); 65362181Sdim if (!APR_STATUS_IS_EBUSY(rv)) { 66362181Sdim if (rv == APR_SUCCESS) { 67362181Sdim mutex->curr_locked = 1; 68362181Sdim } 69362181Sdim break; 70362181Sdim } 71362181Sdim if (timeout <= 0) { 72362181Sdim rv = APR_TIMEUP; 73362181Sdim break; 74362181Sdim } 75362181Sdim if (timeout > SLEEP_TIME) { 76362181Sdim apr_sleep(SLEEP_TIME); 77362181Sdim timeout -= SLEEP_TIME; 78362181Sdim } 79362181Sdim else { 80362181Sdim apr_sleep(timeout); 81362181Sdim timeout = 0; 82362181Sdim } 83362181Sdim } 84362181Sdim return rv; 85362181Sdim} 86362181Sdim#endif 87362181Sdim 88251875Speter#if APR_HAS_POSIXSEM_SERIALIZE 89251875Speter 90251875Speter#ifndef SEM_FAILED 91251875Speter#define SEM_FAILED (-1) 92251875Speter#endif 93251875Speter 94251875Speterstatic apr_status_t proc_mutex_posix_cleanup(void *mutex_) 95251875Speter{ 96251875Speter apr_proc_mutex_t *mutex = mutex_; 97251875Speter 98362181Sdim if (sem_close(mutex->os.psem_interproc) < 0) { 99251875Speter return errno; 100251875Speter } 101251875Speter 102251875Speter return APR_SUCCESS; 103251875Speter} 104251875Speter 105251875Speterstatic unsigned int rshash (char *p) { 106251875Speter /* hash function from Robert Sedgwicks 'Algorithms in C' book */ 107251875Speter unsigned int b = 378551; 108251875Speter unsigned int a = 63689; 109251875Speter unsigned int retval = 0; 110251875Speter 111251875Speter for( ; *p; p++) 112251875Speter { 113251875Speter retval = retval * a + (*p); 114251875Speter a *= b; 115251875Speter } 116251875Speter 117251875Speter return retval; 118251875Speter} 119251875Speter 120251875Speterstatic apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex, 121251875Speter const char *fname) 122251875Speter{ 123251875Speter #define APR_POSIXSEM_NAME_MIN 13 124251875Speter sem_t *psem; 125251875Speter char semname[32]; 126251875Speter 127251875Speter /* 128251875Speter * This bogusness is to follow what appears to be the 129251875Speter * lowest common denominator in Posix semaphore naming: 130251875Speter * - start with '/' 131251875Speter * - be at most 14 chars 132251875Speter * - be unique and not match anything on the filesystem 133251875Speter * 134251875Speter * Because of this, we use fname to generate a (unique) hash 135251875Speter * and use that as the name of the semaphore. If no filename was 136251875Speter * given, we create one based on the time. We tuck the name 137251875Speter * away, since it might be useful for debugging. We use 2 hashing 138251875Speter * functions to try to avoid collisions. 139251875Speter * 140251875Speter * To make this as robust as possible, we initially try something 141251875Speter * larger (and hopefully more unique) and gracefully fail down to the 142251875Speter * LCD above. 143251875Speter * 144251875Speter * NOTE: Darwin (Mac OS X) seems to be the most restrictive 145251875Speter * implementation. Versions previous to Darwin 6.2 had the 14 146251875Speter * char limit, but later rev's allow up to 31 characters. 147251875Speter * 148251875Speter */ 149251875Speter if (fname) { 150251875Speter apr_ssize_t flen = strlen(fname); 151251875Speter char *p = apr_pstrndup(new_mutex->pool, fname, strlen(fname)); 152251875Speter unsigned int h1, h2; 153266735Speter h1 = (apr_hashfunc_default((const char *)p, &flen) & 0xffffffff); 154266735Speter h2 = (rshash(p) & 0xffffffff); 155251875Speter apr_snprintf(semname, sizeof(semname), "/ApR.%xH%x", h1, h2); 156251875Speter } else { 157251875Speter apr_time_t now; 158251875Speter unsigned long sec; 159251875Speter unsigned long usec; 160251875Speter now = apr_time_now(); 161251875Speter sec = apr_time_sec(now); 162251875Speter usec = apr_time_usec(now); 163251875Speter apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec); 164251875Speter } 165286503Speter do { 166286503Speter psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1); 167286503Speter } while (psem == (sem_t *)SEM_FAILED && errno == EINTR); 168251875Speter if (psem == (sem_t *)SEM_FAILED) { 169251875Speter if (errno == ENAMETOOLONG) { 170251875Speter /* Oh well, good try */ 171251875Speter semname[APR_POSIXSEM_NAME_MIN] = '\0'; 172251875Speter } else { 173251875Speter return errno; 174251875Speter } 175286503Speter do { 176286503Speter psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1); 177286503Speter } while (psem == (sem_t *)SEM_FAILED && errno == EINTR); 178251875Speter } 179251875Speter 180251875Speter if (psem == (sem_t *)SEM_FAILED) { 181251875Speter return errno; 182251875Speter } 183251875Speter /* Ahhh. The joys of Posix sems. Predelete it... */ 184251875Speter sem_unlink(semname); 185362181Sdim new_mutex->os.psem_interproc = psem; 186251875Speter new_mutex->fname = apr_pstrdup(new_mutex->pool, semname); 187251875Speter apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, 188251875Speter apr_proc_mutex_cleanup, 189251875Speter apr_pool_cleanup_null); 190251875Speter return APR_SUCCESS; 191251875Speter} 192251875Speter 193251875Speterstatic apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex) 194251875Speter{ 195286503Speter int rc; 196286503Speter 197286503Speter do { 198362181Sdim rc = sem_wait(mutex->os.psem_interproc); 199286503Speter } while (rc < 0 && errno == EINTR); 200286503Speter if (rc < 0) { 201251875Speter return errno; 202251875Speter } 203251875Speter mutex->curr_locked = 1; 204251875Speter return APR_SUCCESS; 205251875Speter} 206251875Speter 207251875Speterstatic apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex) 208251875Speter{ 209286503Speter int rc; 210286503Speter 211286503Speter do { 212362181Sdim rc = sem_trywait(mutex->os.psem_interproc); 213286503Speter } while (rc < 0 && errno == EINTR); 214286503Speter if (rc < 0) { 215251875Speter if (errno == EAGAIN) { 216251875Speter return APR_EBUSY; 217251875Speter } 218251875Speter return errno; 219251875Speter } 220251875Speter mutex->curr_locked = 1; 221251875Speter return APR_SUCCESS; 222251875Speter} 223251875Speter 224362181Sdim#if defined(HAVE_SEM_TIMEDWAIT) 225362181Sdimstatic apr_status_t proc_mutex_posix_timedacquire(apr_proc_mutex_t *mutex, 226362181Sdim apr_interval_time_t timeout) 227362181Sdim{ 228362181Sdim if (timeout <= 0) { 229362181Sdim apr_status_t rv = proc_mutex_posix_tryacquire(mutex); 230362181Sdim return (rv == APR_EBUSY) ? APR_TIMEUP : rv; 231362181Sdim } 232362181Sdim else { 233362181Sdim int rc; 234362181Sdim struct timespec abstime; 235362181Sdim 236362181Sdim timeout += apr_time_now(); 237362181Sdim abstime.tv_sec = apr_time_sec(timeout); 238362181Sdim abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ 239362181Sdim 240362181Sdim do { 241362181Sdim rc = sem_timedwait(mutex->os.psem_interproc, &abstime); 242362181Sdim } while (rc < 0 && errno == EINTR); 243362181Sdim if (rc < 0) { 244362181Sdim if (errno == ETIMEDOUT) { 245362181Sdim return APR_TIMEUP; 246362181Sdim } 247362181Sdim return errno; 248362181Sdim } 249362181Sdim } 250362181Sdim mutex->curr_locked = 1; 251362181Sdim return APR_SUCCESS; 252362181Sdim} 253362181Sdim#endif 254362181Sdim 255251875Speterstatic apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex) 256251875Speter{ 257251875Speter mutex->curr_locked = 0; 258362181Sdim if (sem_post(mutex->os.psem_interproc) < 0) { 259251875Speter /* any failure is probably fatal, so no big deal to leave 260251875Speter * ->curr_locked at 0. */ 261251875Speter return errno; 262251875Speter } 263251875Speter return APR_SUCCESS; 264251875Speter} 265251875Speter 266251875Speterstatic const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods = 267251875Speter{ 268251875Speter#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(POSIXSEM_IS_GLOBAL) 269251875Speter APR_PROCESS_LOCK_MECH_IS_GLOBAL, 270251875Speter#else 271251875Speter 0, 272251875Speter#endif 273251875Speter proc_mutex_posix_create, 274251875Speter proc_mutex_posix_acquire, 275251875Speter proc_mutex_posix_tryacquire, 276362181Sdim#if defined(HAVE_SEM_TIMEDWAIT) 277362181Sdim proc_mutex_posix_timedacquire, 278362181Sdim#else 279362181Sdim proc_mutex_spinsleep_timedacquire, 280362181Sdim#endif 281251875Speter proc_mutex_posix_release, 282251875Speter proc_mutex_posix_cleanup, 283251875Speter proc_mutex_no_child_init, 284362181Sdim proc_mutex_no_perms_set, 285362181Sdim APR_LOCK_POSIXSEM, 286251875Speter "posixsem" 287251875Speter}; 288251875Speter 289251875Speter#endif /* Posix sem implementation */ 290251875Speter 291251875Speter#if APR_HAS_SYSVSEM_SERIALIZE 292251875Speter 293251875Speterstatic struct sembuf proc_mutex_op_on; 294251875Speterstatic struct sembuf proc_mutex_op_try; 295251875Speterstatic struct sembuf proc_mutex_op_off; 296251875Speter 297251875Speterstatic void proc_mutex_sysv_setup(void) 298251875Speter{ 299251875Speter proc_mutex_op_on.sem_num = 0; 300251875Speter proc_mutex_op_on.sem_op = -1; 301251875Speter proc_mutex_op_on.sem_flg = SEM_UNDO; 302251875Speter proc_mutex_op_try.sem_num = 0; 303251875Speter proc_mutex_op_try.sem_op = -1; 304251875Speter proc_mutex_op_try.sem_flg = SEM_UNDO | IPC_NOWAIT; 305251875Speter proc_mutex_op_off.sem_num = 0; 306251875Speter proc_mutex_op_off.sem_op = 1; 307251875Speter proc_mutex_op_off.sem_flg = SEM_UNDO; 308251875Speter} 309251875Speter 310251875Speterstatic apr_status_t proc_mutex_sysv_cleanup(void *mutex_) 311251875Speter{ 312251875Speter apr_proc_mutex_t *mutex=mutex_; 313251875Speter union semun ick; 314251875Speter 315362181Sdim if (mutex->os.crossproc != -1) { 316251875Speter ick.val = 0; 317362181Sdim semctl(mutex->os.crossproc, 0, IPC_RMID, ick); 318251875Speter } 319251875Speter return APR_SUCCESS; 320251875Speter} 321251875Speter 322251875Speterstatic apr_status_t proc_mutex_sysv_create(apr_proc_mutex_t *new_mutex, 323251875Speter const char *fname) 324251875Speter{ 325251875Speter union semun ick; 326251875Speter apr_status_t rv; 327251875Speter 328362181Sdim new_mutex->os.crossproc = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); 329362181Sdim if (new_mutex->os.crossproc == -1) { 330251875Speter rv = errno; 331251875Speter proc_mutex_sysv_cleanup(new_mutex); 332251875Speter return rv; 333251875Speter } 334251875Speter ick.val = 1; 335362181Sdim if (semctl(new_mutex->os.crossproc, 0, SETVAL, ick) < 0) { 336251875Speter rv = errno; 337251875Speter proc_mutex_sysv_cleanup(new_mutex); 338362181Sdim new_mutex->os.crossproc = -1; 339251875Speter return rv; 340251875Speter } 341251875Speter new_mutex->curr_locked = 0; 342251875Speter apr_pool_cleanup_register(new_mutex->pool, 343251875Speter (void *)new_mutex, apr_proc_mutex_cleanup, 344251875Speter apr_pool_cleanup_null); 345251875Speter return APR_SUCCESS; 346251875Speter} 347251875Speter 348251875Speterstatic apr_status_t proc_mutex_sysv_acquire(apr_proc_mutex_t *mutex) 349251875Speter{ 350251875Speter int rc; 351251875Speter 352251875Speter do { 353362181Sdim rc = semop(mutex->os.crossproc, &proc_mutex_op_on, 1); 354251875Speter } while (rc < 0 && errno == EINTR); 355251875Speter if (rc < 0) { 356251875Speter return errno; 357251875Speter } 358251875Speter mutex->curr_locked = 1; 359251875Speter return APR_SUCCESS; 360251875Speter} 361251875Speter 362251875Speterstatic apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex) 363251875Speter{ 364251875Speter int rc; 365251875Speter 366251875Speter do { 367362181Sdim rc = semop(mutex->os.crossproc, &proc_mutex_op_try, 1); 368251875Speter } while (rc < 0 && errno == EINTR); 369251875Speter if (rc < 0) { 370251875Speter if (errno == EAGAIN) { 371251875Speter return APR_EBUSY; 372251875Speter } 373251875Speter return errno; 374251875Speter } 375251875Speter mutex->curr_locked = 1; 376251875Speter return APR_SUCCESS; 377251875Speter} 378251875Speter 379362181Sdim#if defined(HAVE_SEMTIMEDOP) 380362181Sdimstatic apr_status_t proc_mutex_sysv_timedacquire(apr_proc_mutex_t *mutex, 381362181Sdim apr_interval_time_t timeout) 382362181Sdim{ 383362181Sdim if (timeout <= 0) { 384362181Sdim apr_status_t rv = proc_mutex_sysv_tryacquire(mutex); 385362181Sdim return (rv == APR_EBUSY) ? APR_TIMEUP : rv; 386362181Sdim } 387362181Sdim else { 388362181Sdim int rc; 389362181Sdim struct timespec reltime; 390362181Sdim 391362181Sdim reltime.tv_sec = apr_time_sec(timeout); 392362181Sdim reltime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ 393362181Sdim 394362181Sdim do { 395362181Sdim rc = semtimedop(mutex->os.crossproc, &proc_mutex_op_on, 1, 396362181Sdim &reltime); 397362181Sdim } while (rc < 0 && errno == EINTR); 398362181Sdim if (rc < 0) { 399362181Sdim if (errno == EAGAIN) { 400362181Sdim return APR_TIMEUP; 401362181Sdim } 402362181Sdim return errno; 403362181Sdim } 404362181Sdim } 405362181Sdim mutex->curr_locked = 1; 406362181Sdim return APR_SUCCESS; 407362181Sdim} 408362181Sdim#endif 409362181Sdim 410251875Speterstatic apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex) 411251875Speter{ 412251875Speter int rc; 413251875Speter 414251875Speter mutex->curr_locked = 0; 415251875Speter do { 416362181Sdim rc = semop(mutex->os.crossproc, &proc_mutex_op_off, 1); 417251875Speter } while (rc < 0 && errno == EINTR); 418251875Speter if (rc < 0) { 419251875Speter return errno; 420251875Speter } 421251875Speter return APR_SUCCESS; 422251875Speter} 423251875Speter 424362181Sdimstatic apr_status_t proc_mutex_sysv_perms_set(apr_proc_mutex_t *mutex, 425362181Sdim apr_fileperms_t perms, 426362181Sdim apr_uid_t uid, 427362181Sdim apr_gid_t gid) 428362181Sdim{ 429362181Sdim 430362181Sdim union semun ick; 431362181Sdim struct semid_ds buf; 432362181Sdim buf.sem_perm.uid = uid; 433362181Sdim buf.sem_perm.gid = gid; 434362181Sdim buf.sem_perm.mode = apr_unix_perms2mode(perms); 435362181Sdim ick.buf = &buf; 436362181Sdim if (semctl(mutex->os.crossproc, 0, IPC_SET, ick) < 0) { 437362181Sdim return errno; 438362181Sdim } 439362181Sdim return APR_SUCCESS; 440362181Sdim} 441362181Sdim 442251875Speterstatic const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = 443251875Speter{ 444251875Speter#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(SYSVSEM_IS_GLOBAL) 445251875Speter APR_PROCESS_LOCK_MECH_IS_GLOBAL, 446251875Speter#else 447251875Speter 0, 448251875Speter#endif 449251875Speter proc_mutex_sysv_create, 450251875Speter proc_mutex_sysv_acquire, 451251875Speter proc_mutex_sysv_tryacquire, 452362181Sdim#if defined(HAVE_SEMTIMEDOP) 453362181Sdim proc_mutex_sysv_timedacquire, 454362181Sdim#else 455362181Sdim proc_mutex_spinsleep_timedacquire, 456362181Sdim#endif 457251875Speter proc_mutex_sysv_release, 458251875Speter proc_mutex_sysv_cleanup, 459251875Speter proc_mutex_no_child_init, 460362181Sdim proc_mutex_sysv_perms_set, 461362181Sdim APR_LOCK_SYSVSEM, 462251875Speter "sysvsem" 463251875Speter}; 464251875Speter 465251875Speter#endif /* SysV sem implementation */ 466251875Speter 467251875Speter#if APR_HAS_PROC_PTHREAD_SERIALIZE 468251875Speter 469362181Sdim#ifndef APR_USE_PROC_PTHREAD_MUTEX_COND 470362181Sdim#define APR_USE_PROC_PTHREAD_MUTEX_COND \ 471362181Sdim (defined(HAVE_PTHREAD_CONDATTR_SETPSHARED) \ 472362181Sdim && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)) 473362181Sdim#endif 474362181Sdim 475362181Sdim/* The mmap()ed pthread_interproc is the native pthread_mutex_t followed 476362181Sdim * by a refcounter to track children using it. We want to avoid calling 477362181Sdim * pthread_mutex_destroy() on the shared mutex area while it is in use by 478362181Sdim * another process, because this may mark the shared pthread_mutex_t as 479362181Sdim * invalid for everyone, including forked children (unlike "sysvsem" for 480362181Sdim * example), causing unexpected errors or deadlocks (PR 49504). So the 481362181Sdim * last process (parent or child) referencing the mutex will effectively 482362181Sdim * destroy it. 483362181Sdim */ 484362181Sdimtypedef struct { 485362181Sdim#define proc_pthread_cast(m) \ 486362181Sdim ((proc_pthread_mutex_t *)(m)->os.pthread_interproc) 487362181Sdim pthread_mutex_t mutex; 488362181Sdim#define proc_pthread_mutex(m) \ 489362181Sdim (proc_pthread_cast(m)->mutex) 490362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 491362181Sdim pthread_cond_t cond; 492362181Sdim#define proc_pthread_mutex_cond(m) \ 493362181Sdim (proc_pthread_cast(m)->cond) 494362181Sdim apr_int32_t cond_locked; 495362181Sdim#define proc_pthread_mutex_cond_locked(m) \ 496362181Sdim (proc_pthread_cast(m)->cond_locked) 497362181Sdim apr_uint32_t cond_num_waiters; 498362181Sdim#define proc_pthread_mutex_cond_num_waiters(m) \ 499362181Sdim (proc_pthread_cast(m)->cond_num_waiters) 500362181Sdim#define proc_pthread_mutex_is_cond(m) \ 501362181Sdim ((m)->pthread_refcounting && proc_pthread_mutex_cond_locked(m) != -1) 502362181Sdim#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ 503362181Sdim apr_uint32_t refcount; 504362181Sdim#define proc_pthread_mutex_refcount(m) \ 505362181Sdim (proc_pthread_cast(m)->refcount) 506362181Sdim} proc_pthread_mutex_t; 507362181Sdim 508362181Sdim 509362181Sdimstatic APR_INLINE int proc_pthread_mutex_inc(apr_proc_mutex_t *mutex) 510251875Speter{ 511362181Sdim if (mutex->pthread_refcounting) { 512362181Sdim apr_atomic_inc32(&proc_pthread_mutex_refcount(mutex)); 513362181Sdim return 1; 514362181Sdim } 515362181Sdim return 0; 516362181Sdim} 517362181Sdim 518362181Sdimstatic APR_INLINE int proc_pthread_mutex_dec(apr_proc_mutex_t *mutex) 519362181Sdim{ 520362181Sdim if (mutex->pthread_refcounting) { 521362181Sdim return apr_atomic_dec32(&proc_pthread_mutex_refcount(mutex)); 522362181Sdim } 523362181Sdim return 0; 524362181Sdim} 525362181Sdim 526362181Sdimstatic apr_status_t proc_pthread_mutex_unref(void *mutex_) 527362181Sdim{ 528251875Speter apr_proc_mutex_t *mutex=mutex_; 529251875Speter apr_status_t rv; 530251875Speter 531362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 532362181Sdim if (proc_pthread_mutex_is_cond(mutex)) { 533362181Sdim mutex->curr_locked = 0; 534362181Sdim } 535362181Sdim else 536362181Sdim#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ 537251875Speter if (mutex->curr_locked == 1) { 538362181Sdim if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) { 539251875Speter#ifdef HAVE_ZOS_PTHREADS 540251875Speter rv = errno; 541251875Speter#endif 542251875Speter return rv; 543251875Speter } 544251875Speter } 545362181Sdim if (!proc_pthread_mutex_dec(mutex)) { 546362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 547362181Sdim if (proc_pthread_mutex_is_cond(mutex) && 548362181Sdim (rv = pthread_cond_destroy(&proc_pthread_mutex_cond(mutex)))) { 549251875Speter#ifdef HAVE_ZOS_PTHREADS 550251875Speter rv = errno; 551251875Speter#endif 552251875Speter return rv; 553251875Speter } 554362181Sdim#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ 555362181Sdim 556362181Sdim if ((rv = pthread_mutex_destroy(&proc_pthread_mutex(mutex)))) { 557362181Sdim#ifdef HAVE_ZOS_PTHREADS 558362181Sdim rv = errno; 559362181Sdim#endif 560362181Sdim return rv; 561362181Sdim } 562251875Speter } 563362181Sdim return APR_SUCCESS; 564362181Sdim} 565362181Sdim 566362181Sdimstatic apr_status_t proc_mutex_pthread_cleanup(void *mutex_) 567362181Sdim{ 568362181Sdim apr_proc_mutex_t *mutex=mutex_; 569362181Sdim apr_status_t rv; 570362181Sdim 571362181Sdim /* curr_locked is set to -1 until the mutex has been created */ 572362181Sdim if (mutex->curr_locked != -1) { 573362181Sdim if ((rv = proc_pthread_mutex_unref(mutex))) { 574362181Sdim return rv; 575362181Sdim } 576362181Sdim } 577362181Sdim if (munmap(mutex->os.pthread_interproc, sizeof(proc_pthread_mutex_t))) { 578251875Speter return errno; 579251875Speter } 580251875Speter return APR_SUCCESS; 581251875Speter} 582251875Speter 583362181Sdimstatic apr_status_t proc_mutex_pthread_create(apr_proc_mutex_t *new_mutex, 584362181Sdim const char *fname) 585251875Speter{ 586251875Speter apr_status_t rv; 587251875Speter int fd; 588251875Speter pthread_mutexattr_t mattr; 589251875Speter 590251875Speter fd = open("/dev/zero", O_RDWR); 591251875Speter if (fd < 0) { 592251875Speter return errno; 593251875Speter } 594251875Speter 595362181Sdim new_mutex->os.pthread_interproc = mmap(NULL, sizeof(proc_pthread_mutex_t), 596362181Sdim PROT_READ | PROT_WRITE, MAP_SHARED, 597362181Sdim fd, 0); 598362181Sdim if (new_mutex->os.pthread_interproc == MAP_FAILED) { 599362181Sdim new_mutex->os.pthread_interproc = NULL; 600362181Sdim rv = errno; 601251875Speter close(fd); 602362181Sdim return rv; 603251875Speter } 604251875Speter close(fd); 605251875Speter 606362181Sdim new_mutex->pthread_refcounting = 1; 607251875Speter new_mutex->curr_locked = -1; /* until the mutex has been created */ 608362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 609362181Sdim proc_pthread_mutex_cond_locked(new_mutex) = -1; 610362181Sdim#endif 611251875Speter 612251875Speter if ((rv = pthread_mutexattr_init(&mattr))) { 613251875Speter#ifdef HAVE_ZOS_PTHREADS 614251875Speter rv = errno; 615251875Speter#endif 616362181Sdim proc_mutex_pthread_cleanup(new_mutex); 617251875Speter return rv; 618251875Speter } 619251875Speter if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) { 620251875Speter#ifdef HAVE_ZOS_PTHREADS 621251875Speter rv = errno; 622251875Speter#endif 623362181Sdim proc_mutex_pthread_cleanup(new_mutex); 624251875Speter pthread_mutexattr_destroy(&mattr); 625251875Speter return rv; 626251875Speter } 627251875Speter 628362181Sdim#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP) 629251875Speter#ifdef HAVE_PTHREAD_MUTEX_ROBUST 630362181Sdim rv = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); 631362181Sdim#else 632362181Sdim rv = pthread_mutexattr_setrobust_np(&mattr, PTHREAD_MUTEX_ROBUST_NP); 633362181Sdim#endif 634362181Sdim if (rv) { 635251875Speter#ifdef HAVE_ZOS_PTHREADS 636251875Speter rv = errno; 637251875Speter#endif 638362181Sdim proc_mutex_pthread_cleanup(new_mutex); 639251875Speter pthread_mutexattr_destroy(&mattr); 640251875Speter return rv; 641251875Speter } 642251875Speter if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) { 643251875Speter#ifdef HAVE_ZOS_PTHREADS 644251875Speter rv = errno; 645251875Speter#endif 646362181Sdim proc_mutex_pthread_cleanup(new_mutex); 647251875Speter pthread_mutexattr_destroy(&mattr); 648251875Speter return rv; 649251875Speter } 650362181Sdim#endif /* HAVE_PTHREAD_MUTEX_ROBUST[_NP] */ 651251875Speter 652362181Sdim if ((rv = pthread_mutex_init(&proc_pthread_mutex(new_mutex), &mattr))) { 653251875Speter#ifdef HAVE_ZOS_PTHREADS 654251875Speter rv = errno; 655251875Speter#endif 656362181Sdim proc_mutex_pthread_cleanup(new_mutex); 657251875Speter pthread_mutexattr_destroy(&mattr); 658251875Speter return rv; 659251875Speter } 660251875Speter 661362181Sdim proc_pthread_mutex_refcount(new_mutex) = 1; /* first/parent reference */ 662251875Speter new_mutex->curr_locked = 0; /* mutex created now */ 663251875Speter 664251875Speter if ((rv = pthread_mutexattr_destroy(&mattr))) { 665251875Speter#ifdef HAVE_ZOS_PTHREADS 666251875Speter rv = errno; 667251875Speter#endif 668362181Sdim proc_mutex_pthread_cleanup(new_mutex); 669251875Speter return rv; 670251875Speter } 671251875Speter 672251875Speter apr_pool_cleanup_register(new_mutex->pool, 673251875Speter (void *)new_mutex, 674251875Speter apr_proc_mutex_cleanup, 675251875Speter apr_pool_cleanup_null); 676251875Speter return APR_SUCCESS; 677251875Speter} 678251875Speter 679362181Sdimstatic apr_status_t proc_mutex_pthread_child_init(apr_proc_mutex_t **mutex, 680362181Sdim apr_pool_t *pool, 681362181Sdim const char *fname) 682251875Speter{ 683362181Sdim (*mutex)->curr_locked = 0; 684362181Sdim if (proc_pthread_mutex_inc(*mutex)) { 685362181Sdim apr_pool_cleanup_register(pool, *mutex, proc_pthread_mutex_unref, 686362181Sdim apr_pool_cleanup_null); 687362181Sdim } 688362181Sdim return APR_SUCCESS; 689362181Sdim} 690362181Sdim 691362181Sdimstatic apr_status_t proc_mutex_pthread_acquire_ex(apr_proc_mutex_t *mutex, 692362181Sdim apr_interval_time_t timeout) 693362181Sdim{ 694251875Speter apr_status_t rv; 695251875Speter 696362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 697362181Sdim if (proc_pthread_mutex_is_cond(mutex)) { 698362181Sdim if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) { 699362181Sdim#ifdef HAVE_ZOS_PTHREADS 700362181Sdim rv = errno; 701251875Speter#endif 702362181Sdim#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP) 703362181Sdim /* Okay, our owner died. Let's try to make it consistent again. */ 704362181Sdim if (rv == EOWNERDEAD) { 705362181Sdim proc_pthread_mutex_dec(mutex); 706251875Speter#ifdef HAVE_PTHREAD_MUTEX_ROBUST 707362181Sdim pthread_mutex_consistent(&proc_pthread_mutex(mutex)); 708362181Sdim#else 709362181Sdim pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); 710362181Sdim#endif 711362181Sdim } 712362181Sdim else 713362181Sdim#endif 714362181Sdim return rv; 715251875Speter } 716362181Sdim 717362181Sdim if (!proc_pthread_mutex_cond_locked(mutex)) { 718362181Sdim rv = APR_SUCCESS; 719362181Sdim } 720362181Sdim else if (!timeout) { 721362181Sdim rv = APR_TIMEUP; 722362181Sdim } 723362181Sdim else { 724362181Sdim struct timespec abstime; 725362181Sdim 726362181Sdim if (timeout > 0) { 727362181Sdim timeout += apr_time_now(); 728362181Sdim abstime.tv_sec = apr_time_sec(timeout); 729362181Sdim abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ 730362181Sdim } 731362181Sdim 732362181Sdim proc_pthread_mutex_cond_num_waiters(mutex)++; 733362181Sdim do { 734362181Sdim if (timeout < 0) { 735362181Sdim rv = pthread_cond_wait(&proc_pthread_mutex_cond(mutex), 736362181Sdim &proc_pthread_mutex(mutex)); 737362181Sdim if (rv) { 738362181Sdim#ifdef HAVE_ZOS_PTHREADS 739362181Sdim rv = errno; 740362181Sdim#endif 741362181Sdim break; 742362181Sdim } 743362181Sdim } 744362181Sdim else { 745362181Sdim rv = pthread_cond_timedwait(&proc_pthread_mutex_cond(mutex), 746362181Sdim &proc_pthread_mutex(mutex), 747362181Sdim &abstime); 748362181Sdim if (rv) { 749362181Sdim#ifdef HAVE_ZOS_PTHREADS 750362181Sdim rv = errno; 751362181Sdim#endif 752362181Sdim if (rv == ETIMEDOUT) { 753362181Sdim rv = APR_TIMEUP; 754362181Sdim } 755362181Sdim break; 756362181Sdim } 757362181Sdim } 758362181Sdim } while (proc_pthread_mutex_cond_locked(mutex)); 759362181Sdim proc_pthread_mutex_cond_num_waiters(mutex)--; 760362181Sdim } 761362181Sdim if (rv != APR_SUCCESS) { 762362181Sdim pthread_mutex_unlock(&proc_pthread_mutex(mutex)); 763362181Sdim return rv; 764362181Sdim } 765362181Sdim 766362181Sdim proc_pthread_mutex_cond_locked(mutex) = 1; 767362181Sdim 768362181Sdim rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)); 769362181Sdim if (rv) { 770362181Sdim#ifdef HAVE_ZOS_PTHREADS 771362181Sdim rv = errno; 772362181Sdim#endif 773362181Sdim return rv; 774362181Sdim } 775362181Sdim } 776362181Sdim else 777362181Sdim#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ 778362181Sdim { 779362181Sdim if (timeout < 0) { 780362181Sdim rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)); 781362181Sdim if (rv) { 782362181Sdim#ifdef HAVE_ZOS_PTHREADS 783362181Sdim rv = errno; 784362181Sdim#endif 785362181Sdim } 786362181Sdim } 787362181Sdim else if (!timeout) { 788362181Sdim rv = pthread_mutex_trylock(&proc_pthread_mutex(mutex)); 789362181Sdim if (rv) { 790362181Sdim#ifdef HAVE_ZOS_PTHREADS 791362181Sdim rv = errno; 792362181Sdim#endif 793362181Sdim if (rv == EBUSY) { 794362181Sdim return APR_TIMEUP; 795362181Sdim } 796362181Sdim } 797362181Sdim } 798251875Speter else 799362181Sdim#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) 800362181Sdim { 801362181Sdim struct timespec abstime; 802362181Sdim 803362181Sdim timeout += apr_time_now(); 804362181Sdim abstime.tv_sec = apr_time_sec(timeout); 805362181Sdim abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ 806362181Sdim 807362181Sdim rv = pthread_mutex_timedlock(&proc_pthread_mutex(mutex), &abstime); 808362181Sdim if (rv) { 809362181Sdim#ifdef HAVE_ZOS_PTHREADS 810362181Sdim rv = errno; 811362181Sdim#endif 812362181Sdim if (rv == ETIMEDOUT) { 813362181Sdim return APR_TIMEUP; 814362181Sdim } 815362181Sdim } 816362181Sdim } 817362181Sdim if (rv) { 818362181Sdim#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP) 819362181Sdim /* Okay, our owner died. Let's try to make it consistent again. */ 820362181Sdim if (rv == EOWNERDEAD) { 821362181Sdim proc_pthread_mutex_dec(mutex); 822362181Sdim#ifdef HAVE_PTHREAD_MUTEX_ROBUST 823362181Sdim pthread_mutex_consistent(&proc_pthread_mutex(mutex)); 824251875Speter#else 825362181Sdim pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); 826251875Speter#endif 827362181Sdim } 828362181Sdim else 829362181Sdim#endif 830362181Sdim return rv; 831362181Sdim } 832362181Sdim#else /* !HAVE_PTHREAD_MUTEX_TIMEDLOCK */ 833362181Sdim return proc_mutex_spinsleep_timedacquire(mutex, timeout); 834362181Sdim#endif 835251875Speter } 836362181Sdim 837251875Speter mutex->curr_locked = 1; 838251875Speter return APR_SUCCESS; 839251875Speter} 840251875Speter 841362181Sdimstatic apr_status_t proc_mutex_pthread_acquire(apr_proc_mutex_t *mutex) 842251875Speter{ 843362181Sdim return proc_mutex_pthread_acquire_ex(mutex, -1); 844362181Sdim} 845362181Sdim 846362181Sdimstatic apr_status_t proc_mutex_pthread_tryacquire(apr_proc_mutex_t *mutex) 847362181Sdim{ 848362181Sdim apr_status_t rv = proc_mutex_pthread_acquire_ex(mutex, 0); 849362181Sdim return (rv == APR_TIMEUP) ? APR_EBUSY : rv; 850362181Sdim} 851362181Sdim 852362181Sdimstatic apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, 853362181Sdim apr_interval_time_t timeout) 854362181Sdim{ 855362181Sdim return proc_mutex_pthread_acquire_ex(mutex, (timeout <= 0) ? 0 : timeout); 856362181Sdim} 857362181Sdim 858362181Sdimstatic apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex) 859362181Sdim{ 860251875Speter apr_status_t rv; 861362181Sdim 862362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 863362181Sdim if (proc_pthread_mutex_is_cond(mutex)) { 864362181Sdim if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) { 865251875Speter#ifdef HAVE_ZOS_PTHREADS 866362181Sdim rv = errno; 867251875Speter#endif 868362181Sdim#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP) 869362181Sdim /* Okay, our owner died. Let's try to make it consistent again. */ 870362181Sdim if (rv == EOWNERDEAD) { 871362181Sdim proc_pthread_mutex_dec(mutex); 872362181Sdim#ifdef HAVE_PTHREAD_MUTEX_ROBUST 873362181Sdim pthread_mutex_consistent(&proc_pthread_mutex(mutex)); 874362181Sdim#else 875362181Sdim pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); 876362181Sdim#endif 877362181Sdim } 878362181Sdim else 879362181Sdim#endif 880362181Sdim return rv; 881251875Speter } 882362181Sdim 883362181Sdim if (!proc_pthread_mutex_cond_locked(mutex)) { 884362181Sdim rv = APR_EINVAL; 885362181Sdim } 886362181Sdim else if (!proc_pthread_mutex_cond_num_waiters(mutex)) { 887251875Speter rv = APR_SUCCESS; 888251875Speter } 889362181Sdim else { 890362181Sdim rv = pthread_cond_signal(&proc_pthread_mutex_cond(mutex)); 891362181Sdim#ifdef HAVE_ZOS_PTHREADS 892362181Sdim if (rv) { 893362181Sdim rv = errno; 894362181Sdim } 895362181Sdim#endif 896362181Sdim } 897362181Sdim if (rv != APR_SUCCESS) { 898362181Sdim pthread_mutex_unlock(&proc_pthread_mutex(mutex)); 899251875Speter return rv; 900362181Sdim } 901362181Sdim 902362181Sdim proc_pthread_mutex_cond_locked(mutex) = 0; 903362181Sdim } 904362181Sdim#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ 905362181Sdim 906362181Sdim mutex->curr_locked = 0; 907362181Sdim if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) { 908362181Sdim#ifdef HAVE_ZOS_PTHREADS 909362181Sdim rv = errno; 910362181Sdim#endif 911251875Speter return rv; 912251875Speter } 913362181Sdim 914362181Sdim return APR_SUCCESS; 915251875Speter} 916251875Speter 917362181Sdimstatic const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = 918251875Speter{ 919362181Sdim APR_PROCESS_LOCK_MECH_IS_GLOBAL, 920362181Sdim proc_mutex_pthread_create, 921362181Sdim proc_mutex_pthread_acquire, 922362181Sdim proc_mutex_pthread_tryacquire, 923362181Sdim proc_mutex_pthread_timedacquire, 924362181Sdim proc_mutex_pthread_release, 925362181Sdim proc_mutex_pthread_cleanup, 926362181Sdim proc_mutex_pthread_child_init, 927362181Sdim proc_mutex_no_perms_set, 928362181Sdim APR_LOCK_PROC_PTHREAD, 929362181Sdim "pthread" 930362181Sdim}; 931362181Sdim 932362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 933362181Sdimstatic apr_status_t proc_mutex_pthread_cond_create(apr_proc_mutex_t *new_mutex, 934362181Sdim const char *fname) 935362181Sdim{ 936251875Speter apr_status_t rv; 937362181Sdim pthread_condattr_t cattr; 938251875Speter 939362181Sdim rv = proc_mutex_pthread_create(new_mutex, fname); 940362181Sdim if (rv != APR_SUCCESS) { 941362181Sdim return rv; 942362181Sdim } 943362181Sdim 944362181Sdim if ((rv = pthread_condattr_init(&cattr))) { 945251875Speter#ifdef HAVE_ZOS_PTHREADS 946251875Speter rv = errno; 947251875Speter#endif 948362181Sdim apr_pool_cleanup_run(new_mutex->pool, new_mutex, 949362181Sdim apr_proc_mutex_cleanup); 950251875Speter return rv; 951251875Speter } 952362181Sdim if ((rv = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))) { 953362181Sdim#ifdef HAVE_ZOS_PTHREADS 954362181Sdim rv = errno; 955362181Sdim#endif 956362181Sdim pthread_condattr_destroy(&cattr); 957362181Sdim apr_pool_cleanup_run(new_mutex->pool, new_mutex, 958362181Sdim apr_proc_mutex_cleanup); 959362181Sdim return rv; 960362181Sdim } 961362181Sdim if ((rv = pthread_cond_init(&proc_pthread_mutex_cond(new_mutex), 962362181Sdim &cattr))) { 963362181Sdim#ifdef HAVE_ZOS_PTHREADS 964362181Sdim rv = errno; 965362181Sdim#endif 966362181Sdim pthread_condattr_destroy(&cattr); 967362181Sdim apr_pool_cleanup_run(new_mutex->pool, new_mutex, 968362181Sdim apr_proc_mutex_cleanup); 969362181Sdim return rv; 970362181Sdim } 971362181Sdim pthread_condattr_destroy(&cattr); 972362181Sdim 973362181Sdim proc_pthread_mutex_cond_locked(new_mutex) = 0; 974362181Sdim proc_pthread_mutex_cond_num_waiters(new_mutex) = 0; 975362181Sdim 976251875Speter return APR_SUCCESS; 977251875Speter} 978251875Speter 979362181Sdimstatic const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_cond_methods = 980251875Speter{ 981251875Speter APR_PROCESS_LOCK_MECH_IS_GLOBAL, 982362181Sdim proc_mutex_pthread_cond_create, 983362181Sdim proc_mutex_pthread_acquire, 984362181Sdim proc_mutex_pthread_tryacquire, 985362181Sdim proc_mutex_pthread_timedacquire, 986362181Sdim proc_mutex_pthread_release, 987362181Sdim proc_mutex_pthread_cleanup, 988362181Sdim proc_mutex_pthread_child_init, 989362181Sdim proc_mutex_no_perms_set, 990362181Sdim APR_LOCK_PROC_PTHREAD, 991251875Speter "pthread" 992251875Speter}; 993362181Sdim#endif 994251875Speter 995251875Speter#endif 996251875Speter 997251875Speter#if APR_HAS_FCNTL_SERIALIZE 998251875Speter 999251875Speterstatic struct flock proc_mutex_lock_it; 1000251875Speterstatic struct flock proc_mutex_unlock_it; 1001251875Speter 1002251875Speterstatic apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *); 1003251875Speter 1004251875Speterstatic void proc_mutex_fcntl_setup(void) 1005251875Speter{ 1006251875Speter proc_mutex_lock_it.l_whence = SEEK_SET; /* from current point */ 1007251875Speter proc_mutex_lock_it.l_start = 0; /* -"- */ 1008251875Speter proc_mutex_lock_it.l_len = 0; /* until end of file */ 1009251875Speter proc_mutex_lock_it.l_type = F_WRLCK; /* set exclusive/write lock */ 1010251875Speter proc_mutex_lock_it.l_pid = 0; /* pid not actually interesting */ 1011251875Speter proc_mutex_unlock_it.l_whence = SEEK_SET; /* from current point */ 1012251875Speter proc_mutex_unlock_it.l_start = 0; /* -"- */ 1013251875Speter proc_mutex_unlock_it.l_len = 0; /* until end of file */ 1014251875Speter proc_mutex_unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */ 1015251875Speter proc_mutex_unlock_it.l_pid = 0; /* pid not actually interesting */ 1016251875Speter} 1017251875Speter 1018251875Speterstatic apr_status_t proc_mutex_fcntl_cleanup(void *mutex_) 1019251875Speter{ 1020362181Sdim apr_status_t status = APR_SUCCESS; 1021251875Speter apr_proc_mutex_t *mutex=mutex_; 1022251875Speter 1023251875Speter if (mutex->curr_locked == 1) { 1024251875Speter status = proc_mutex_fcntl_release(mutex); 1025251875Speter if (status != APR_SUCCESS) 1026251875Speter return status; 1027251875Speter } 1028251875Speter 1029362181Sdim if (mutex->interproc) { 1030362181Sdim status = apr_file_close(mutex->interproc); 1031362181Sdim } 1032362181Sdim if (!mutex->interproc_closing 1033362181Sdim && mutex->os.crossproc != -1 1034362181Sdim && close(mutex->os.crossproc) == -1 1035362181Sdim && status == APR_SUCCESS) { 1036362181Sdim status = errno; 1037362181Sdim } 1038362181Sdim return status; 1039251875Speter} 1040251875Speter 1041251875Speterstatic apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex, 1042251875Speter const char *fname) 1043251875Speter{ 1044251875Speter int rv; 1045251875Speter 1046251875Speter if (fname) { 1047251875Speter new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); 1048251875Speter rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, 1049251875Speter APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL, 1050251875Speter APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD, 1051251875Speter new_mutex->pool); 1052251875Speter } 1053251875Speter else { 1054251875Speter new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); 1055251875Speter rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, 1056251875Speter APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL, 1057251875Speter new_mutex->pool); 1058251875Speter } 1059251875Speter 1060251875Speter if (rv != APR_SUCCESS) { 1061251875Speter return rv; 1062251875Speter } 1063251875Speter 1064362181Sdim new_mutex->os.crossproc = new_mutex->interproc->filedes; 1065362181Sdim new_mutex->interproc_closing = 1; 1066251875Speter new_mutex->curr_locked = 0; 1067251875Speter unlink(new_mutex->fname); 1068251875Speter apr_pool_cleanup_register(new_mutex->pool, 1069251875Speter (void*)new_mutex, 1070251875Speter apr_proc_mutex_cleanup, 1071251875Speter apr_pool_cleanup_null); 1072251875Speter return APR_SUCCESS; 1073251875Speter} 1074251875Speter 1075251875Speterstatic apr_status_t proc_mutex_fcntl_acquire(apr_proc_mutex_t *mutex) 1076251875Speter{ 1077251875Speter int rc; 1078251875Speter 1079251875Speter do { 1080362181Sdim rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_lock_it); 1081251875Speter } while (rc < 0 && errno == EINTR); 1082251875Speter if (rc < 0) { 1083251875Speter return errno; 1084251875Speter } 1085251875Speter mutex->curr_locked=1; 1086251875Speter return APR_SUCCESS; 1087251875Speter} 1088251875Speter 1089251875Speterstatic apr_status_t proc_mutex_fcntl_tryacquire(apr_proc_mutex_t *mutex) 1090251875Speter{ 1091251875Speter int rc; 1092251875Speter 1093251875Speter do { 1094362181Sdim rc = fcntl(mutex->os.crossproc, F_SETLK, &proc_mutex_lock_it); 1095251875Speter } while (rc < 0 && errno == EINTR); 1096251875Speter if (rc < 0) { 1097251875Speter#if FCNTL_TRYACQUIRE_EACCES 1098251875Speter if (errno == EACCES) { 1099251875Speter#else 1100251875Speter if (errno == EAGAIN) { 1101251875Speter#endif 1102251875Speter return APR_EBUSY; 1103251875Speter } 1104251875Speter return errno; 1105251875Speter } 1106251875Speter mutex->curr_locked = 1; 1107251875Speter return APR_SUCCESS; 1108251875Speter} 1109251875Speter 1110251875Speterstatic apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex) 1111251875Speter{ 1112251875Speter int rc; 1113251875Speter 1114251875Speter mutex->curr_locked=0; 1115251875Speter do { 1116362181Sdim rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_unlock_it); 1117251875Speter } while (rc < 0 && errno == EINTR); 1118251875Speter if (rc < 0) { 1119251875Speter return errno; 1120251875Speter } 1121251875Speter return APR_SUCCESS; 1122251875Speter} 1123251875Speter 1124362181Sdimstatic apr_status_t proc_mutex_fcntl_perms_set(apr_proc_mutex_t *mutex, 1125362181Sdim apr_fileperms_t perms, 1126362181Sdim apr_uid_t uid, 1127362181Sdim apr_gid_t gid) 1128362181Sdim{ 1129362181Sdim 1130362181Sdim if (mutex->fname) { 1131362181Sdim if (!(perms & APR_FPROT_GSETID)) 1132362181Sdim gid = -1; 1133362181Sdim if (fchown(mutex->os.crossproc, uid, gid) < 0) { 1134362181Sdim return errno; 1135362181Sdim } 1136362181Sdim } 1137362181Sdim return APR_SUCCESS; 1138362181Sdim} 1139362181Sdim 1140251875Speterstatic const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods = 1141251875Speter{ 1142251875Speter#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FCNTL_IS_GLOBAL) 1143251875Speter APR_PROCESS_LOCK_MECH_IS_GLOBAL, 1144251875Speter#else 1145251875Speter 0, 1146251875Speter#endif 1147251875Speter proc_mutex_fcntl_create, 1148251875Speter proc_mutex_fcntl_acquire, 1149251875Speter proc_mutex_fcntl_tryacquire, 1150362181Sdim proc_mutex_spinsleep_timedacquire, 1151251875Speter proc_mutex_fcntl_release, 1152251875Speter proc_mutex_fcntl_cleanup, 1153251875Speter proc_mutex_no_child_init, 1154362181Sdim proc_mutex_fcntl_perms_set, 1155362181Sdim APR_LOCK_FCNTL, 1156251875Speter "fcntl" 1157251875Speter}; 1158251875Speter 1159251875Speter#endif /* fcntl implementation */ 1160251875Speter 1161251875Speter#if APR_HAS_FLOCK_SERIALIZE 1162251875Speter 1163251875Speterstatic apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *); 1164251875Speter 1165251875Speterstatic apr_status_t proc_mutex_flock_cleanup(void *mutex_) 1166251875Speter{ 1167362181Sdim apr_status_t status = APR_SUCCESS; 1168251875Speter apr_proc_mutex_t *mutex=mutex_; 1169251875Speter 1170251875Speter if (mutex->curr_locked == 1) { 1171251875Speter status = proc_mutex_flock_release(mutex); 1172251875Speter if (status != APR_SUCCESS) 1173251875Speter return status; 1174251875Speter } 1175251875Speter if (mutex->interproc) { /* if it was opened properly */ 1176362181Sdim status = apr_file_close(mutex->interproc); 1177251875Speter } 1178362181Sdim if (!mutex->interproc_closing 1179362181Sdim && mutex->os.crossproc != -1 1180362181Sdim && close(mutex->os.crossproc) == -1 1181362181Sdim && status == APR_SUCCESS) { 1182362181Sdim status = errno; 1183362181Sdim } 1184362181Sdim if (mutex->fname) { 1185362181Sdim unlink(mutex->fname); 1186362181Sdim } 1187362181Sdim return status; 1188251875Speter} 1189251875Speter 1190251875Speterstatic apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex, 1191251875Speter const char *fname) 1192251875Speter{ 1193251875Speter int rv; 1194251875Speter 1195251875Speter if (fname) { 1196251875Speter new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); 1197251875Speter rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, 1198251875Speter APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL, 1199251875Speter APR_UREAD | APR_UWRITE, 1200251875Speter new_mutex->pool); 1201251875Speter } 1202251875Speter else { 1203251875Speter new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); 1204251875Speter rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, 1205251875Speter APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL, 1206251875Speter new_mutex->pool); 1207251875Speter } 1208251875Speter 1209251875Speter if (rv != APR_SUCCESS) { 1210251875Speter proc_mutex_flock_cleanup(new_mutex); 1211362181Sdim return rv; 1212251875Speter } 1213362181Sdim 1214362181Sdim new_mutex->os.crossproc = new_mutex->interproc->filedes; 1215362181Sdim new_mutex->interproc_closing = 1; 1216251875Speter new_mutex->curr_locked = 0; 1217251875Speter apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, 1218251875Speter apr_proc_mutex_cleanup, 1219251875Speter apr_pool_cleanup_null); 1220251875Speter return APR_SUCCESS; 1221251875Speter} 1222251875Speter 1223251875Speterstatic apr_status_t proc_mutex_flock_acquire(apr_proc_mutex_t *mutex) 1224251875Speter{ 1225251875Speter int rc; 1226251875Speter 1227251875Speter do { 1228362181Sdim rc = flock(mutex->os.crossproc, LOCK_EX); 1229251875Speter } while (rc < 0 && errno == EINTR); 1230251875Speter if (rc < 0) { 1231251875Speter return errno; 1232251875Speter } 1233251875Speter mutex->curr_locked = 1; 1234251875Speter return APR_SUCCESS; 1235251875Speter} 1236251875Speter 1237251875Speterstatic apr_status_t proc_mutex_flock_tryacquire(apr_proc_mutex_t *mutex) 1238251875Speter{ 1239251875Speter int rc; 1240251875Speter 1241251875Speter do { 1242362181Sdim rc = flock(mutex->os.crossproc, LOCK_EX | LOCK_NB); 1243251875Speter } while (rc < 0 && errno == EINTR); 1244251875Speter if (rc < 0) { 1245251875Speter if (errno == EWOULDBLOCK || errno == EAGAIN) { 1246251875Speter return APR_EBUSY; 1247251875Speter } 1248251875Speter return errno; 1249251875Speter } 1250251875Speter mutex->curr_locked = 1; 1251251875Speter return APR_SUCCESS; 1252251875Speter} 1253251875Speter 1254251875Speterstatic apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex) 1255251875Speter{ 1256251875Speter int rc; 1257251875Speter 1258251875Speter mutex->curr_locked = 0; 1259251875Speter do { 1260362181Sdim rc = flock(mutex->os.crossproc, LOCK_UN); 1261251875Speter } while (rc < 0 && errno == EINTR); 1262251875Speter if (rc < 0) { 1263251875Speter return errno; 1264251875Speter } 1265251875Speter return APR_SUCCESS; 1266251875Speter} 1267251875Speter 1268251875Speterstatic apr_status_t proc_mutex_flock_child_init(apr_proc_mutex_t **mutex, 1269251875Speter apr_pool_t *pool, 1270251875Speter const char *fname) 1271251875Speter{ 1272251875Speter apr_proc_mutex_t *new_mutex; 1273251875Speter int rv; 1274251875Speter 1275251875Speter if (!fname) { 1276251875Speter fname = (*mutex)->fname; 1277362181Sdim if (!fname) { 1278362181Sdim return APR_SUCCESS; 1279362181Sdim } 1280251875Speter } 1281362181Sdim 1282362181Sdim new_mutex = (apr_proc_mutex_t *)apr_pmemdup(pool, *mutex, 1283362181Sdim sizeof(apr_proc_mutex_t)); 1284362181Sdim new_mutex->pool = pool; 1285251875Speter new_mutex->fname = apr_pstrdup(pool, fname); 1286251875Speter rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, 1287251875Speter APR_FOPEN_WRITE, 0, new_mutex->pool); 1288251875Speter if (rv != APR_SUCCESS) { 1289251875Speter return rv; 1290251875Speter } 1291362181Sdim new_mutex->os.crossproc = new_mutex->interproc->filedes; 1292362181Sdim new_mutex->interproc_closing = 1; 1293362181Sdim 1294251875Speter *mutex = new_mutex; 1295251875Speter return APR_SUCCESS; 1296251875Speter} 1297251875Speter 1298362181Sdimstatic apr_status_t proc_mutex_flock_perms_set(apr_proc_mutex_t *mutex, 1299362181Sdim apr_fileperms_t perms, 1300362181Sdim apr_uid_t uid, 1301362181Sdim apr_gid_t gid) 1302362181Sdim{ 1303362181Sdim 1304362181Sdim if (mutex->fname) { 1305362181Sdim if (!(perms & APR_FPROT_GSETID)) 1306362181Sdim gid = -1; 1307362181Sdim if (fchown(mutex->os.crossproc, uid, gid) < 0) { 1308362181Sdim return errno; 1309362181Sdim } 1310362181Sdim } 1311362181Sdim return APR_SUCCESS; 1312362181Sdim} 1313362181Sdim 1314251875Speterstatic const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods = 1315251875Speter{ 1316251875Speter#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FLOCK_IS_GLOBAL) 1317251875Speter APR_PROCESS_LOCK_MECH_IS_GLOBAL, 1318251875Speter#else 1319251875Speter 0, 1320251875Speter#endif 1321251875Speter proc_mutex_flock_create, 1322251875Speter proc_mutex_flock_acquire, 1323251875Speter proc_mutex_flock_tryacquire, 1324362181Sdim proc_mutex_spinsleep_timedacquire, 1325251875Speter proc_mutex_flock_release, 1326251875Speter proc_mutex_flock_cleanup, 1327251875Speter proc_mutex_flock_child_init, 1328362181Sdim proc_mutex_flock_perms_set, 1329362181Sdim APR_LOCK_FLOCK, 1330251875Speter "flock" 1331251875Speter}; 1332251875Speter 1333251875Speter#endif /* flock implementation */ 1334251875Speter 1335251875Spetervoid apr_proc_mutex_unix_setup_lock(void) 1336251875Speter{ 1337251875Speter /* setup only needed for sysvsem and fnctl */ 1338251875Speter#if APR_HAS_SYSVSEM_SERIALIZE 1339251875Speter proc_mutex_sysv_setup(); 1340251875Speter#endif 1341251875Speter#if APR_HAS_FCNTL_SERIALIZE 1342251875Speter proc_mutex_fcntl_setup(); 1343251875Speter#endif 1344251875Speter} 1345251875Speter 1346362181Sdimstatic apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, 1347362181Sdim apr_lockmech_e mech, 1348362181Sdim apr_os_proc_mutex_t *ospmutex) 1349251875Speter{ 1350362181Sdim#if APR_HAS_PROC_PTHREAD_SERIALIZE 1351362181Sdim new_mutex->os.pthread_interproc = NULL; 1352362181Sdim#endif 1353362181Sdim#if APR_HAS_POSIXSEM_SERIALIZE 1354362181Sdim new_mutex->os.psem_interproc = NULL; 1355362181Sdim#endif 1356362181Sdim#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE 1357362181Sdim new_mutex->os.crossproc = -1; 1358362181Sdim 1359362181Sdim#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE 1360362181Sdim new_mutex->interproc = NULL; 1361362181Sdim new_mutex->interproc_closing = 0; 1362362181Sdim#endif 1363362181Sdim#endif 1364362181Sdim 1365251875Speter switch (mech) { 1366251875Speter case APR_LOCK_FCNTL: 1367251875Speter#if APR_HAS_FCNTL_SERIALIZE 1368362181Sdim new_mutex->meth = &mutex_fcntl_methods; 1369362181Sdim if (ospmutex) { 1370362181Sdim if (ospmutex->crossproc == -1) { 1371362181Sdim return APR_EINVAL; 1372362181Sdim } 1373362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1374362181Sdim } 1375251875Speter#else 1376251875Speter return APR_ENOTIMPL; 1377251875Speter#endif 1378251875Speter break; 1379251875Speter case APR_LOCK_FLOCK: 1380251875Speter#if APR_HAS_FLOCK_SERIALIZE 1381362181Sdim new_mutex->meth = &mutex_flock_methods; 1382362181Sdim if (ospmutex) { 1383362181Sdim if (ospmutex->crossproc == -1) { 1384362181Sdim return APR_EINVAL; 1385362181Sdim } 1386362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1387362181Sdim } 1388251875Speter#else 1389251875Speter return APR_ENOTIMPL; 1390251875Speter#endif 1391251875Speter break; 1392251875Speter case APR_LOCK_SYSVSEM: 1393251875Speter#if APR_HAS_SYSVSEM_SERIALIZE 1394362181Sdim new_mutex->meth = &mutex_sysv_methods; 1395362181Sdim if (ospmutex) { 1396362181Sdim if (ospmutex->crossproc == -1) { 1397362181Sdim return APR_EINVAL; 1398362181Sdim } 1399362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1400362181Sdim } 1401251875Speter#else 1402251875Speter return APR_ENOTIMPL; 1403251875Speter#endif 1404251875Speter break; 1405251875Speter case APR_LOCK_POSIXSEM: 1406251875Speter#if APR_HAS_POSIXSEM_SERIALIZE 1407362181Sdim new_mutex->meth = &mutex_posixsem_methods; 1408362181Sdim if (ospmutex) { 1409362181Sdim if (ospmutex->psem_interproc == NULL) { 1410362181Sdim return APR_EINVAL; 1411362181Sdim } 1412362181Sdim new_mutex->os.psem_interproc = ospmutex->psem_interproc; 1413362181Sdim } 1414251875Speter#else 1415251875Speter return APR_ENOTIMPL; 1416251875Speter#endif 1417251875Speter break; 1418251875Speter case APR_LOCK_PROC_PTHREAD: 1419251875Speter#if APR_HAS_PROC_PTHREAD_SERIALIZE 1420362181Sdim new_mutex->meth = &mutex_proc_pthread_methods; 1421362181Sdim if (ospmutex) { 1422362181Sdim if (ospmutex->pthread_interproc == NULL) { 1423362181Sdim return APR_EINVAL; 1424362181Sdim } 1425362181Sdim new_mutex->os.pthread_interproc = ospmutex->pthread_interproc; 1426362181Sdim } 1427251875Speter#else 1428251875Speter return APR_ENOTIMPL; 1429251875Speter#endif 1430251875Speter break; 1431362181Sdim case APR_LOCK_DEFAULT_TIMED: 1432362181Sdim#if APR_HAS_PROC_PTHREAD_SERIALIZE \ 1433362181Sdim && (APR_USE_PROC_PTHREAD_MUTEX_COND \ 1434362181Sdim || defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)) \ 1435362181Sdim && defined(HAVE_PTHREAD_MUTEX_ROBUST) 1436362181Sdim#if APR_USE_PROC_PTHREAD_MUTEX_COND 1437362181Sdim new_mutex->meth = &mutex_proc_pthread_cond_methods; 1438362181Sdim#else 1439362181Sdim new_mutex->meth = &mutex_proc_pthread_methods; 1440362181Sdim#endif 1441362181Sdim if (ospmutex) { 1442362181Sdim if (ospmutex->pthread_interproc == NULL) { 1443362181Sdim return APR_EINVAL; 1444362181Sdim } 1445362181Sdim new_mutex->os.pthread_interproc = ospmutex->pthread_interproc; 1446362181Sdim } 1447362181Sdim break; 1448362181Sdim#elif APR_HAS_SYSVSEM_SERIALIZE && defined(HAVE_SEMTIMEDOP) 1449362181Sdim new_mutex->meth = &mutex_sysv_methods; 1450362181Sdim if (ospmutex) { 1451362181Sdim if (ospmutex->crossproc == -1) { 1452362181Sdim return APR_EINVAL; 1453362181Sdim } 1454362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1455362181Sdim } 1456362181Sdim break; 1457362181Sdim#elif APR_HAS_POSIXSEM_SERIALIZE && defined(HAVE_SEM_TIMEDWAIT) 1458362181Sdim new_mutex->meth = &mutex_posixsem_methods; 1459362181Sdim if (ospmutex) { 1460362181Sdim if (ospmutex->psem_interproc == NULL) { 1461362181Sdim return APR_EINVAL; 1462362181Sdim } 1463362181Sdim new_mutex->os.psem_interproc = ospmutex->psem_interproc; 1464362181Sdim } 1465362181Sdim break; 1466362181Sdim#endif 1467362181Sdim /* fall trough */ 1468251875Speter case APR_LOCK_DEFAULT: 1469251875Speter#if APR_USE_FLOCK_SERIALIZE 1470362181Sdim new_mutex->meth = &mutex_flock_methods; 1471362181Sdim if (ospmutex) { 1472362181Sdim if (ospmutex->crossproc == -1) { 1473362181Sdim return APR_EINVAL; 1474362181Sdim } 1475362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1476362181Sdim } 1477251875Speter#elif APR_USE_SYSVSEM_SERIALIZE 1478362181Sdim new_mutex->meth = &mutex_sysv_methods; 1479362181Sdim if (ospmutex) { 1480362181Sdim if (ospmutex->crossproc == -1) { 1481362181Sdim return APR_EINVAL; 1482362181Sdim } 1483362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1484362181Sdim } 1485251875Speter#elif APR_USE_FCNTL_SERIALIZE 1486362181Sdim new_mutex->meth = &mutex_fcntl_methods; 1487362181Sdim if (ospmutex) { 1488362181Sdim if (ospmutex->crossproc == -1) { 1489362181Sdim return APR_EINVAL; 1490362181Sdim } 1491362181Sdim new_mutex->os.crossproc = ospmutex->crossproc; 1492362181Sdim } 1493251875Speter#elif APR_USE_PROC_PTHREAD_SERIALIZE 1494362181Sdim new_mutex->meth = &mutex_proc_pthread_methods; 1495362181Sdim if (ospmutex) { 1496362181Sdim if (ospmutex->pthread_interproc == NULL) { 1497362181Sdim return APR_EINVAL; 1498362181Sdim } 1499362181Sdim new_mutex->os.pthread_interproc = ospmutex->pthread_interproc; 1500362181Sdim } 1501251875Speter#elif APR_USE_POSIXSEM_SERIALIZE 1502362181Sdim new_mutex->meth = &mutex_posixsem_methods; 1503362181Sdim if (ospmutex) { 1504362181Sdim if (ospmutex->psem_interproc == NULL) { 1505362181Sdim return APR_EINVAL; 1506362181Sdim } 1507362181Sdim new_mutex->os.psem_interproc = ospmutex->psem_interproc; 1508362181Sdim } 1509251875Speter#else 1510251875Speter return APR_ENOTIMPL; 1511251875Speter#endif 1512251875Speter break; 1513251875Speter default: 1514251875Speter return APR_ENOTIMPL; 1515251875Speter } 1516251875Speter return APR_SUCCESS; 1517251875Speter} 1518251875Speter 1519251875SpeterAPR_DECLARE(const char *) apr_proc_mutex_defname(void) 1520251875Speter{ 1521251875Speter apr_status_t rv; 1522251875Speter apr_proc_mutex_t mutex; 1523251875Speter 1524362181Sdim if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT, 1525362181Sdim NULL)) != APR_SUCCESS) { 1526251875Speter return "unknown"; 1527251875Speter } 1528251875Speter 1529251875Speter return apr_proc_mutex_name(&mutex); 1530251875Speter} 1531251875Speter 1532251875Speterstatic apr_status_t proc_mutex_create(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech, const char *fname) 1533251875Speter{ 1534251875Speter apr_status_t rv; 1535251875Speter 1536362181Sdim if ((rv = proc_mutex_choose_method(new_mutex, mech, 1537362181Sdim NULL)) != APR_SUCCESS) { 1538251875Speter return rv; 1539251875Speter } 1540251875Speter 1541251875Speter if ((rv = new_mutex->meth->create(new_mutex, fname)) != APR_SUCCESS) { 1542251875Speter return rv; 1543251875Speter } 1544251875Speter 1545251875Speter return APR_SUCCESS; 1546251875Speter} 1547251875Speter 1548251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, 1549251875Speter const char *fname, 1550251875Speter apr_lockmech_e mech, 1551251875Speter apr_pool_t *pool) 1552251875Speter{ 1553251875Speter apr_proc_mutex_t *new_mutex; 1554251875Speter apr_status_t rv; 1555251875Speter 1556251875Speter new_mutex = apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); 1557251875Speter new_mutex->pool = pool; 1558251875Speter 1559251875Speter if ((rv = proc_mutex_create(new_mutex, mech, fname)) != APR_SUCCESS) 1560251875Speter return rv; 1561251875Speter 1562251875Speter *mutex = new_mutex; 1563251875Speter return APR_SUCCESS; 1564251875Speter} 1565251875Speter 1566251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, 1567251875Speter const char *fname, 1568251875Speter apr_pool_t *pool) 1569251875Speter{ 1570251875Speter return (*mutex)->meth->child_init(mutex, pool, fname); 1571251875Speter} 1572251875Speter 1573251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) 1574251875Speter{ 1575251875Speter return mutex->meth->acquire(mutex); 1576251875Speter} 1577251875Speter 1578251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) 1579251875Speter{ 1580251875Speter return mutex->meth->tryacquire(mutex); 1581251875Speter} 1582251875Speter 1583362181SdimAPR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex, 1584362181Sdim apr_interval_time_t timeout) 1585362181Sdim{ 1586362181Sdim#if APR_HAS_TIMEDLOCKS 1587362181Sdim return mutex->meth->timedacquire(mutex, timeout); 1588362181Sdim#else 1589362181Sdim return APR_ENOTIMPL; 1590362181Sdim#endif 1591362181Sdim} 1592362181Sdim 1593251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) 1594251875Speter{ 1595251875Speter return mutex->meth->release(mutex); 1596251875Speter} 1597251875Speter 1598251875SpeterAPR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) 1599251875Speter{ 1600251875Speter return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex); 1601251875Speter} 1602251875Speter 1603362181SdimAPR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex) 1604362181Sdim{ 1605362181Sdim return mutex->meth->mech; 1606362181Sdim} 1607362181Sdim 1608251875SpeterAPR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) 1609251875Speter{ 1610251875Speter return mutex->meth->name; 1611251875Speter} 1612251875Speter 1613251875SpeterAPR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) 1614251875Speter{ 1615251875Speter /* POSIX sems use the fname field but don't use a file, 1616251875Speter * so be careful. */ 1617251875Speter#if APR_HAS_FLOCK_SERIALIZE 1618251875Speter if (mutex->meth == &mutex_flock_methods) { 1619251875Speter return mutex->fname; 1620251875Speter } 1621251875Speter#endif 1622251875Speter#if APR_HAS_FCNTL_SERIALIZE 1623251875Speter if (mutex->meth == &mutex_fcntl_methods) { 1624251875Speter return mutex->fname; 1625251875Speter } 1626251875Speter#endif 1627251875Speter return NULL; 1628251875Speter} 1629251875Speter 1630362181SdimAPR_PERMS_SET_IMPLEMENT(proc_mutex) 1631362181Sdim{ 1632362181Sdim apr_proc_mutex_t *mutex = (apr_proc_mutex_t *)theproc_mutex; 1633362181Sdim return mutex->meth->perms_set(mutex, perms, uid, gid); 1634362181Sdim} 1635362181Sdim 1636251875SpeterAPR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) 1637251875Speter 1638251875Speter/* Implement OS-specific accessors defined in apr_portable.h */ 1639251875Speter 1640362181SdimAPR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 1641362181Sdim apr_proc_mutex_t *pmutex, 1642362181Sdim apr_lockmech_e *mech) 1643251875Speter{ 1644362181Sdim *ospmutex = pmutex->os; 1645362181Sdim if (mech) { 1646362181Sdim *mech = pmutex->meth->mech; 1647266735Speter } 1648251875Speter return APR_SUCCESS; 1649251875Speter} 1650251875Speter 1651362181SdimAPR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, 1652362181Sdim apr_proc_mutex_t *pmutex) 1653362181Sdim{ 1654362181Sdim return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL); 1655362181Sdim} 1656362181Sdim 1657362181SdimAPR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex, 1658251875Speter apr_os_proc_mutex_t *ospmutex, 1659362181Sdim apr_lockmech_e mech, 1660362181Sdim int register_cleanup, 1661251875Speter apr_pool_t *pool) 1662251875Speter{ 1663362181Sdim apr_status_t rv; 1664251875Speter if (pool == NULL) { 1665251875Speter return APR_ENOPOOL; 1666251875Speter } 1667362181Sdim 1668251875Speter if ((*pmutex) == NULL) { 1669251875Speter (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, 1670251875Speter sizeof(apr_proc_mutex_t)); 1671251875Speter (*pmutex)->pool = pool; 1672251875Speter } 1673362181Sdim rv = proc_mutex_choose_method(*pmutex, mech, ospmutex); 1674362181Sdim#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE 1675362181Sdim if (rv == APR_SUCCESS) { 1676362181Sdim rv = apr_os_file_put(&(*pmutex)->interproc, &(*pmutex)->os.crossproc, 1677362181Sdim 0, pool); 1678362181Sdim } 1679251875Speter#endif 1680362181Sdim 1681362181Sdim if (rv == APR_SUCCESS && register_cleanup) { 1682362181Sdim apr_pool_cleanup_register(pool, *pmutex, apr_proc_mutex_cleanup, 1683362181Sdim apr_pool_cleanup_null); 1684362181Sdim } 1685362181Sdim return rv; 1686251875Speter} 1687251875Speter 1688362181SdimAPR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, 1689362181Sdim apr_os_proc_mutex_t *ospmutex, 1690362181Sdim apr_pool_t *pool) 1691362181Sdim{ 1692362181Sdim return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT, 1693362181Sdim 0, pool); 1694362181Sdim} 1695362181Sdim 1696