int main() { pthread_t to, ti; pthread_mutexattr_t ma; assert(pthread_mutexattr_init(&ma) == 0); assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0); lockCount = 0; assert(pthread_mutex_init(&mutex[0], &ma) == 0); assert(pthread_mutex_init(&mutex[1], &ma) == 0); assert(pthread_mutex_init(&mutex[2], &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_create(&ti, NULL, inheritor, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 6); assert(pthread_mutex_lock(&mutex[0]) == EOWNERDEAD); assert(pthread_mutex_consistent(&mutex[0]) == 0); assert(pthread_mutex_unlock(&mutex[0]) == 0); assert(pthread_mutex_destroy(&mutex[0]) == 0); assert(pthread_mutex_lock(&mutex[1]) == EOWNERDEAD); assert(pthread_mutex_consistent(&mutex[1]) == 0); assert(pthread_mutex_unlock(&mutex[1]) == 0); assert(pthread_mutex_destroy(&mutex[1]) == 0); assert(pthread_mutex_lock(&mutex[2]) == EOWNERDEAD); assert(pthread_mutex_consistent(&mutex[2]) == 0); assert(pthread_mutex_unlock(&mutex[2]) == 0); assert(pthread_mutex_destroy(&mutex[2]) == 0); assert(pthread_mutexattr_destroy(&ma) == 0); return 0; }
void mutex_init(void) { /* 共享存储初始化 */ if ((fd = open(shared_file, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE)) < 0) err_sys("open error"); if ((pmutex = mmap(0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == NULL) err_sys("mmap error"); /* 互斥量初始化 */ if ((pthread_mutexattr_init(&attr)) != 0) err_sys("pthread_mutexattr_init error"); if ((pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) != 0) { pthread_mutexattr_destroy(&attr); err_sys("pthread_mutexattr_setpshared error"); } /* 参考资料:http://blog.csdn.net/red_knight/article/details/50417898 */ if ((pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) != 0) { pthread_mutexattr_destroy(&attr); err_sys("pthread_mutexattr_setpshared error"); } if ((pthread_mutex_init(pmutex, &attr)) != 0) { pthread_mutexattr_destroy(&attr); err_sys("pthread_mutex_init error"); } pthread_mutexattr_destroy(&attr); }
static void f() { pthread_t td; int r; pthread_mutexattr_t mtx_a; pthread_mutex_t mtx; struct timespec ts; T(r, pthread_barrier_init(&barrier2, 0, 2)); T(r, pthread_mutexattr_init(&mtx_a)); T(r, pthread_mutexattr_setrobust(&mtx_a, PTHREAD_MUTEX_ROBUST)); if (pshared) T(r, pthread_mutexattr_setpshared(&mtx_a, PTHREAD_PROCESS_SHARED)); T(r, pthread_mutex_init(&mtx, &mtx_a)); T(r, pthread_create(&td, 0, start_lock, &mtx)); T(r, pthread_detach(td)); pthread_barrier_wait(&barrier2); pthread_barrier_destroy(&barrier2); // enough time to ensure that the detached thread is dead clock_gettime(CLOCK_REALTIME, &ts); ts.tv_nsec += 100*1000*1000; if (ts.tv_nsec >= 1000*1000*1000) { ts.tv_sec++; ts.tv_nsec -= 1000*1000*1000; } TX(r, pthread_mutex_timedlock(&mtx, &ts), EOWNERDEAD); }
/** * Mutex */ LPDM_MUTEX mutexNew(const char *name) { LPDM_MUTEX m = NULL; #ifdef WIN32 m = CreateMutexA(NULL, FALSE, name); if(m == NULL){ DWORD dwError = GetLastError(); if(dwError == ERROR_ACCESS_DENIED) m = OpenMutexA(SYNCHRONIZE, FALSE, name); } #else pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); m = (LPDM_MUTEX)malloc(sizeof(DM_MUTEX)); m->context = NULL; if(name){ int mutexexist = 0; mutexexist = shm_exist(name); m->context = mmapOpen(name, sizeof(pthread_mutex_t)); m->mutex = (pthread_mutex_t*)m->context->data; if(mutexexist) return m; pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); pthread_mutexattr_setrobust(&mutexattr, PTHREAD_MUTEX_ROBUST); } else m->mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(m->mutex, &mutexattr); pthread_mutexattr_destroy(&mutexattr); #endif return m; }
int tdb_mutex_init(struct tdb_context *tdb) { struct tdb_mutexes *m; pthread_mutexattr_t ma; int i, ret; ret = tdb_mutex_mmap(tdb); if (ret == -1) { return -1; } m = tdb->mutexes; ret = pthread_mutexattr_init(&ma); if (ret != 0) { goto fail_munmap; } ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { goto fail; } ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { goto fail; } ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); if (ret != 0) { goto fail; } for (i=0; i<tdb->hash_size+1; i++) { pthread_mutex_t *chain = &m->hashchains[i]; ret = pthread_mutex_init(chain, &ma); if (ret != 0) { goto fail; } } m->allrecord_lock = F_UNLCK; ret = pthread_mutex_init(&m->allrecord_mutex, &ma); if (ret != 0) { goto fail; } ret = 0; fail: pthread_mutexattr_destroy(&ma); fail_munmap: if (ret == 0) { return 0; } tdb_mutex_munmap(tdb); errno = ret; return -1; }
int mutex_init (pthread_mutex_t *mutex, int flags, int robust) { pthread_mutexattr_t mattr; pthread_mutexattr_init (&mattr); pthread_mutexattr_settype (&mattr, flags); pthread_mutexattr_setrobust (&mattr, robust); return pthread_mutex_init (mutex, &mattr); }
/*! * \brief Create the share memory mutex. * * \param key Shared memory key. * \param addr Starting address of attached shared memory. * \param size Shared memory size. */ static void shm_mutex_create(key_t key, void *addr, size_t size) { pthread_mutex_t *pmutex = (pthread_mutex_t *)addr; pthread_mutexattr_t mutexAttr; pthread_mutexattr_init(&mutexAttr); // // Set the attribute to share between applications. // if(pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED) < 0) { LOGSYSERROR("pthread_mutexattr_setpshared()"); } #ifndef ARCH_overo // // Set mutex robust attribute. If the owning thread or application terminates, // the next thread/application acquiring the mutex is notified by the // return value EOWNERDEAD. // else if( pthread_mutexattr_setrobust(&mutexAttr, PTHREAD_MUTEX_ROBUST) < 0 ) { LOGSYSERROR("pthread_mutexattr_setrobust()"); } // // Allow recursive locks by the owning thread or application. // else if( pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) < 0 ) { LOGSYSERROR("pthread_mutexattr_settype()"); } #endif // ARCH_overo // // Initialize the pthread mutex with the give attributes // else if( pthread_mutex_init(pmutex, &mutexAttr) < 0 ) { LOGSYSERROR("pthread_mutex_init()"); } // // Success. // else { LOGDIAG4("Shared memory mutex created."); } pthread_mutexattr_destroy(&mutexAttr); }
void init_logging() { pthread_mutexattr_t mutexattr; loglevel = LOG_INFO; is_a_tty = isatty(STDOUT_FILENO); pthread_mutexattr_init(&mutexattr); #ifndef __APPLE__ pthread_mutexattr_setrobust(&mutexattr, PTHREAD_MUTEX_ROBUST); #endif pthread_mutex_init(&mutex, &mutexattr); }
CThreadMutex::CThreadMutex(void) { #ifdef _WINDOWS m_Crit = new CRITICAL_SECTION; InitializeCriticalSection( (LPCRITICAL_SECTION)m_Crit ); //No Error Code here #else pthread_mutexattr_t ma; CHECK_UNIX_ERROR(pthread_mutexattr_init(&ma)); CHECK_UNIX_ERROR(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE)); CHECK_UNIX_ERROR(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_STALLED)); CHECK_UNIX_ERROR(pthread_mutex_init(&m_mutex, &ma)); CHECK_UNIX_ERROR(pthread_mutexattr_destroy(&ma)); #endif }
static int do_test (void) { pthread_mutexattr_t a; if (pthread_mutexattr_init (&a) != 0) { puts ("mutexattr_init failed"); return 1; } if (pthread_mutexattr_setrobust (&a, PTHREAD_MUTEX_ROBUST) != 0) { puts ("mutexattr_setrobust failed"); return 1; } #ifdef ENABLE_PI if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) { puts ("pthread_mutexattr_setprotocol failed"); return 1; } #endif int e; e = pthread_mutex_init (&m, &a); if (e != 0) { #ifdef ENABLE_PI if (e == ENOTSUP) { puts ("PI robust mutexes not supported"); return 0; } #endif puts ("mutex_init failed"); return 1; } if (pthread_mutexattr_destroy (&a) != 0) { puts ("mutexattr_destroy failed"); return 1; } if (pthread_barrier_init (&b, NULL, 2) != 0) { puts ("barrier_init failed"); return 1; } #define N 5 pthread_t th[N]; for (long int n = 0; n < N; ++n) { if (pthread_create (&th[n], NULL, tf, (void *) n) != 0) { printf ("pthread_create loop %ld failed\n", n + 1); return 1; } e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { printf ("parent: barrier_wait failed in round %ld\n", n + 1); return 1; } } if (pthread_mutex_lock (&m) != 0) { puts ("parent: mutex_lock failed"); return 1; } if (pthread_mutex_unlock (&m) != 0) { puts ("parent: mutex_unlock failed"); return 1; } if (pthread_cond_broadcast (&c) != 0) { puts ("cond_broadcast failed"); return 1; } for (int n = 0; n < N; ++n) { void *res; if (pthread_join (th[n], &res) != 0) { printf ("join round %d failed\n", n + 1); return 1; } if (res != PTHREAD_CANCELED) { printf ("thread %d not canceled\n", n + 1); return 1; } } e = pthread_mutex_lock (&m); if (e == 0) { puts ("parent: 2nd mutex_lock succeeded"); return 1; } if (e != EOWNERDEAD) { puts ("parent: mutex_lock did not return EOWNERDEAD"); return 1; } if (pthread_mutex_unlock (&m) != 0) { puts ("parent: 2nd mutex_unlock failed"); return 1; } if (pthread_mutex_destroy (&m) != 0) { puts ("mutex_destroy failed"); return 1; } return 0; }
int main() { pthread_t to, ti; pthread_mutexattr_t ma; int order[3]; assert(pthread_mutexattr_init(&ma) == 0); assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0); order[0]=0; order[1]=1; order[2]=2; lockCount = 0; assert(pthread_mutex_init(&mutex[0], &ma) == 0); assert(pthread_mutex_init(&mutex[1], &ma) == 0); assert(pthread_mutex_init(&mutex[2], &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 6); assert(pthread_mutex_lock(&mutex[0]) == 0); assert(pthread_mutex_unlock(&mutex[0]) == 0); assert(pthread_mutex_destroy(&mutex[0]) == 0); assert(pthread_mutex_lock(&mutex[1]) == 0); assert(pthread_mutex_unlock(&mutex[1]) == 0); assert(pthread_mutex_destroy(&mutex[1]) == 0); assert(pthread_mutex_lock(&mutex[2]) == 0); assert(pthread_mutex_unlock(&mutex[2]) == 0); assert(pthread_mutex_destroy(&mutex[2]) == 0); order[0]=1; order[1]=0; order[2]=2; lockCount = 0; assert(pthread_mutex_init(&mutex[0], &ma) == 0); assert(pthread_mutex_init(&mutex[1], &ma) == 0); assert(pthread_mutex_init(&mutex[2], &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 6); assert(pthread_mutex_lock(&mutex[0]) == 0); assert(pthread_mutex_unlock(&mutex[0]) == 0); assert(pthread_mutex_destroy(&mutex[0]) == 0); assert(pthread_mutex_lock(&mutex[1]) == 0); assert(pthread_mutex_unlock(&mutex[1]) == 0); assert(pthread_mutex_destroy(&mutex[1]) == 0); assert(pthread_mutex_lock(&mutex[2]) == 0); assert(pthread_mutex_unlock(&mutex[2]) == 0); assert(pthread_mutex_destroy(&mutex[2]) == 0); order[0]=0; order[1]=2; order[2]=1; lockCount = 0; assert(pthread_mutex_init(&mutex[0], &ma) == 0); assert(pthread_mutex_init(&mutex[1], &ma) == 0); assert(pthread_mutex_init(&mutex[2], &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 6); assert(pthread_mutex_lock(&mutex[0]) == 0); assert(pthread_mutex_unlock(&mutex[0]) == 0); assert(pthread_mutex_destroy(&mutex[0]) == 0); assert(pthread_mutex_lock(&mutex[1]) == 0); assert(pthread_mutex_unlock(&mutex[1]) == 0); assert(pthread_mutex_destroy(&mutex[1]) == 0); assert(pthread_mutex_lock(&mutex[2]) == 0); assert(pthread_mutex_unlock(&mutex[2]) == 0); assert(pthread_mutex_destroy(&mutex[2]) == 0); order[0]=2; order[1]=1; order[2]=0; lockCount = 0; assert(pthread_mutex_init(&mutex[0], &ma) == 0); assert(pthread_mutex_init(&mutex[1], &ma) == 0); assert(pthread_mutex_init(&mutex[2], &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, (void *)order) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 6); assert(pthread_mutex_lock(&mutex[0]) == 0); assert(pthread_mutex_unlock(&mutex[0]) == 0); assert(pthread_mutex_destroy(&mutex[0]) == 0); assert(pthread_mutex_lock(&mutex[1]) == 0); assert(pthread_mutex_unlock(&mutex[1]) == 0); assert(pthread_mutex_destroy(&mutex[1]) == 0); assert(pthread_mutex_lock(&mutex[2]) == 0); assert(pthread_mutex_unlock(&mutex[2]) == 0); assert(pthread_mutex_destroy(&mutex[2]) == 0); assert(pthread_mutexattr_destroy(&ma) == 0); return 0; }
int main (int argc, char *argv[]) { pthread_t t; assert(pthread_mutexattr_init(&ma) == 0); printf( "=============================================================================\n"); printf( "\nTrylock on a locked mutex.\n"); printf( "%ld iterations.\n\n", ITERATIONS); printf( "%-45s %15s %15s\n", "Test", "Total(msec)", "average(usec)"); printf( "-----------------------------------------------------------------------------\n"); /* * Time the loop overhead so we can subtract it from the actual test times. */ TESTSTART TESTSTOP durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; overHeadMilliSecs = durationMilliSecs; old_mutex_use = OLD_WIN32CS; assert(old_mutex_init(&ox, NULL) == 0); assert(old_mutex_lock(&ox) == 0); assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0); assert(pthread_join(t, NULL) == 0); assert(old_mutex_unlock(&ox) == 0); assert(old_mutex_destroy(&ox) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Critical Section (WNT)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); old_mutex_use = OLD_WIN32MUTEX; assert(old_mutex_init(&ox, NULL) == 0); assert(old_mutex_lock(&ox) == 0); assert(pthread_create(&t, NULL, oldTrylockThread, 0) == 0); assert(pthread_join(t, NULL) == 0); assert(old_mutex_unlock(&ox) == 0); assert(old_mutex_destroy(&ox) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Win32 Mutex (W9x)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); printf( ".............................................................................\n"); /* * Now we can start the actual tests */ #ifdef __PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( ".............................................................................\n"); pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); #ifdef __PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( "=============================================================================\n"); /* * End of tests. */ pthread_mutexattr_destroy(&ma); return 0; }
enum ach_status ach_create( const char *channel_name, size_t frame_cnt, size_t frame_size, ach_create_attr_t *attr) { ach_header_t *shm; int fd; size_t len; /* fixme: truncate */ /* open shm */ { len = sizeof( ach_header_t) + frame_cnt*sizeof( ach_index_t ) + frame_cnt*frame_size + 3*sizeof(uint64_t); if( attr && attr->map_anon ) { /* anonymous (heap) */ shm = (ach_header_t *) malloc( len ); fd = -1; }else { int oflag = O_EXCL | O_CREAT; /* shm */ if( ! channel_name_ok( channel_name ) ) return ACH_INVALID_NAME; if( attr ) { if( attr->truncate ) oflag &= ~O_EXCL; } if( (fd = fd_for_channel_name( channel_name, oflag )) < 0 ) { return check_errno();; } { /* make file proper size */ /* FreeBSD needs ftruncate before mmap, Linux can do either order */ int r; int i = 0; do { r = ftruncate( fd, (off_t) len ); }while(-1 == r && EINTR == errno && i++ < ACH_INTR_RETRY); if( -1 == r ) { DEBUG_PERROR( "ftruncate"); return ACH_FAILED_SYSCALL; } } /* mmap */ if( (shm = (ach_header_t *)mmap( NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0) ) == MAP_FAILED ) { DEBUG_PERROR("mmap"); DEBUGF("mmap failed %s, len: %"PRIuPTR", fd: %d\n", strerror(errno), len, fd); return ACH_FAILED_SYSCALL; } } memset( shm, 0, len ); shm->len = len; } { /* initialize synchronization */ { /* initialize condition variables */ int r; pthread_condattr_t cond_attr; if( (r = pthread_condattr_init(&cond_attr)) ) { DEBUG_PERROR("pthread_condattr_init"); return ACH_FAILED_SYSCALL; } /* Process Shared */ if( ! (attr && attr->map_anon) ) { /* Set shared if not anonymous mapping Default will be private. */ if( (r = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED)) ) { DEBUG_PERROR("pthread_condattr_setpshared"); return ACH_FAILED_SYSCALL; } } /* Clock */ if( attr && attr->set_clock ) { if( (r = pthread_condattr_setclock(&cond_attr, attr->clock)) ) { DEBUG_PERROR("pthread_condattr_setclock"); return ACH_FAILED_SYSCALL; } } else { if( (r = pthread_condattr_setclock(&cond_attr, ACH_DEFAULT_CLOCK)) ) { DEBUG_PERROR("pthread_condattr_setclock"); return ACH_FAILED_SYSCALL; } } if( (r = pthread_cond_init(&shm->sync.cond, &cond_attr)) ) { DEBUG_PERROR("pthread_cond_init"); return ACH_FAILED_SYSCALL; } if( (r = pthread_condattr_destroy(&cond_attr)) ) { DEBUG_PERROR("pthread_condattr_destroy"); return ACH_FAILED_SYSCALL; } } { /* initialize mutex */ int r; pthread_mutexattr_t mutex_attr; if( (r = pthread_mutexattr_init(&mutex_attr)) ) { DEBUG_PERROR("pthread_mutexattr_init"); return ACH_FAILED_SYSCALL; } if( (r = pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)) ) { DEBUG_PERROR("pthread_mutexattr_setpshared"); return ACH_FAILED_SYSCALL; } #ifdef HAVE_MUTEX_PRIORITY_INHERIT /* Priority Inheritance Mutex */ if( (r = pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT)) ) { DEBUG_PERROR("pthread_mutexattr_setprotocol"); return ACH_FAILED_SYSCALL; } #endif #ifdef HAVE_MUTEX_ROBUST /* Robust Mutex */ if( (r = pthread_mutexattr_setrobust(&mutex_attr, PTHREAD_MUTEX_ROBUST)) ) { DEBUG_PERROR("pthread_mutexattr_setrobust"); return ACH_FAILED_SYSCALL; } #endif #ifdef HAVE_MUTEX_ERROR_CHECK /* Error Checking Mutex */ if( (r = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK)) ) { DEBUG_PERROR("pthread_mutexattr_settype"); return ACH_FAILED_SYSCALL; } #endif if( (r = pthread_mutex_init(&shm->sync.mutex, &mutex_attr)) ) { DEBUG_PERROR("pthread_mutexattr_init"); return ACH_FAILED_SYSCALL; } if( (r = pthread_mutexattr_destroy(&mutex_attr)) ) { DEBUG_PERROR("pthread_mutexattr_destroy"); return ACH_FAILED_SYSCALL; } } } /* initialize name */ strncpy( shm->name, channel_name, ACH_CHAN_NAME_MAX ); /* initialize counts */ shm->index_cnt = frame_cnt; shm->index_head = 0; shm->index_free = frame_cnt; shm->data_head = 0; shm->data_free = frame_cnt * frame_size; shm->data_size = frame_cnt * frame_size; assert( sizeof( ach_header_t ) + shm->index_free * sizeof( ach_index_t ) + shm->data_free + 3*sizeof(uint64_t) == len ); *ACH_SHM_GUARD_HEADER(shm) = ACH_SHM_GUARD_HEADER_NUM; *ACH_SHM_GUARD_INDEX(shm) = ACH_SHM_GUARD_INDEX_NUM; *ACH_SHM_GUARD_DATA(shm) = ACH_SHM_GUARD_DATA_NUM; shm->magic = ACH_SHM_MAGIC_NUM; if( attr && attr->map_anon ) { attr->shm = shm; } else { int r; /* remove mapping */ r = munmap(shm, len); if( 0 != r ){ DEBUG_PERROR("munmap"); return ACH_FAILED_SYSCALL; } /* close file */ int i = 0; do { IFDEBUG( i ? DEBUGF("Retrying close()\n"):0 ); r = close(fd); }while( -1 == r && EINTR == errno && i++ < ACH_INTR_RETRY ); if( -1 == r ){ DEBUG_PERROR("close"); return ACH_FAILED_SYSCALL; } } return ACH_OK; }
int main (int argc, char *argv[]) { int i = 0; CRITICAL_SECTION cs; old_mutex_t ox; pthread_mutexattr_init(&ma); printf( "=============================================================================\n"); printf( "\nLock plus unlock on an unlocked mutex.\n%ld iterations\n\n", ITERATIONS); printf( "%-45s %15s %15s\n", "Test", "Total(msec)", "average(usec)"); printf( "-----------------------------------------------------------------------------\n"); /* * Time the loop overhead so we can subtract it from the actual test times. */ TESTSTART assert(1 == one); assert(2 == two); TESTSTOP durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; overHeadMilliSecs = durationMilliSecs; TESTSTART assert((dummy_call(&i), 1) == one); assert((dummy_call(&i), 2) == two); TESTSTOP durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Dummy call x 2", durationMilliSecs, (float) (durationMilliSecs * 1E3 / ITERATIONS)); TESTSTART assert((interlocked_inc_with_conditionals(&i), 1) == one); assert((interlocked_dec_with_conditionals(&i), 2) == two); TESTSTOP durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Dummy call -> Interlocked with cond x 2", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); TESTSTART assert((InterlockedIncrement((LPLONG)&i), 1) == (LONG)one); assert((InterlockedDecrement((LPLONG)&i), 2) == (LONG)two); TESTSTOP durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "InterlockedOp x 2", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); InitializeCriticalSection(&cs); TESTSTART assert((EnterCriticalSection(&cs), 1) == one); assert((LeaveCriticalSection(&cs), 2) == two); TESTSTOP DeleteCriticalSection(&cs); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Simple Critical Section", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); old_mutex_use = OLD_WIN32CS; assert(old_mutex_init(&ox, NULL) == 0); TESTSTART assert(old_mutex_lock(&ox) == zero); assert(old_mutex_unlock(&ox) == zero); TESTSTOP assert(old_mutex_destroy(&ox) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Critical Section (WNT)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); old_mutex_use = OLD_WIN32MUTEX; assert(old_mutex_init(&ox, NULL) == 0); TESTSTART assert(old_mutex_lock(&ox) == zero); assert(old_mutex_unlock(&ox) == zero); TESTSTOP assert(old_mutex_destroy(&ox) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Win32 Mutex (W9x)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS); printf( ".............................................................................\n"); /* * Now we can start the actual tests */ #ifdef PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( ".............................................................................\n"); pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); #ifdef PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( "=============================================================================\n"); /* * End of tests. */ pthread_mutexattr_destroy(&ma); one = i; /* Dummy assignment to avoid 'variable unused' warning */ return 0; }
_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void) { void *ptr = NULL; pthread_mutex_t *m = NULL; pthread_mutexattr_t ma; int ret = 1; int pipe_down[2] = { -1, -1 }; int pipe_up[2] = { -1, -1 }; ssize_t nread; char c = 0; bool ok; static bool initialized; pid_t saved_child_pid = -1; bool cleanup_ma = false; if (initialized) { return tdb_mutex_locking_cached; } initialized = true; ok = tdb_mutex_locking_supported(); if (!ok) { return false; } tdb_mutex_locking_cached = false; ptr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1 /* fd */, 0); if (ptr == MAP_FAILED) { return false; } ret = pipe(pipe_down); if (ret != 0) { goto cleanup; } ret = pipe(pipe_up); if (ret != 0) { goto cleanup; } ret = pthread_mutexattr_init(&ma); if (ret != 0) { goto cleanup; } cleanup_ma = true; ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { goto cleanup; } ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { goto cleanup; } ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); if (ret != 0) { goto cleanup; } ret = pthread_mutex_init(ptr, &ma); if (ret != 0) { goto cleanup; } m = (pthread_mutex_t *)ptr; if (tdb_robust_mutex_setup_sigchild(tdb_robust_mutex_handler, &tdb_robust_mutext_old_handler) == false) { goto cleanup; } tdb_robust_mutex_pid = fork(); saved_child_pid = tdb_robust_mutex_pid; if (tdb_robust_mutex_pid == 0) { size_t nwritten; close(pipe_down[1]); close(pipe_up[0]); ret = pthread_mutex_lock(m); nwritten = write(pipe_up[1], &ret, sizeof(ret)); if (nwritten != sizeof(ret)) { _exit(1); } if (ret != 0) { _exit(1); } nread = read(pipe_down[0], &c, 1); if (nread != 1) { _exit(1); } /* leave locked */ _exit(0); } if (tdb_robust_mutex_pid == -1) { goto cleanup; } close(pipe_down[0]); pipe_down[0] = -1; close(pipe_up[1]); pipe_up[1] = -1; nread = read(pipe_up[0], &ret, sizeof(ret)); if (nread != sizeof(ret)) { goto cleanup; } ret = pthread_mutex_trylock(m); if (ret != EBUSY) { if (ret == 0) { pthread_mutex_unlock(m); } goto cleanup; } if (write(pipe_down[1], &c, 1) != 1) { goto cleanup; } nread = read(pipe_up[0], &c, 1); if (nread != 0) { goto cleanup; } tdb_robust_mutex_wait_for_child(&saved_child_pid); ret = pthread_mutex_trylock(m); if (ret != EOWNERDEAD) { if (ret == 0) { pthread_mutex_unlock(m); } goto cleanup; } ret = pthread_mutex_consistent(m); if (ret != 0) { goto cleanup; } ret = pthread_mutex_trylock(m); if (ret != EDEADLK && ret != EBUSY) { pthread_mutex_unlock(m); goto cleanup; } ret = pthread_mutex_unlock(m); if (ret != 0) { goto cleanup; } tdb_mutex_locking_cached = true; cleanup: /* * Note that we don't reset the signal handler we just reset * tdb_robust_mutex_pid to -1. This is ok as this code path is only * called once per process. * * Leaving our signal handler avoids races with other threads potentialy * setting up their SIGCHLD handlers. * * The worst thing that can happen is that the other newer signal * handler will get the SIGCHLD signal for our child and/or reap the * child with a wait() function. tdb_robust_mutex_wait_for_child() * handles the case where waitpid returns ECHILD. */ tdb_robust_mutex_wait_for_child(&saved_child_pid); if (m != NULL) { pthread_mutex_destroy(m); } if (cleanup_ma) { pthread_mutexattr_destroy(&ma); } if (pipe_down[0] != -1) { close(pipe_down[0]); } if (pipe_down[1] != -1) { close(pipe_down[1]); } if (pipe_up[0] != -1) { close(pipe_up[0]); } if (pipe_up[1] != -1) { close(pipe_up[1]); } if (ptr != NULL) { munmap(ptr, sizeof(pthread_mutex_t)); } return tdb_mutex_locking_cached; }
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!! struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) { pthread_mutexattr_t attr; struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0); #ifdef EOWNERDEAD retry: #endif if (pthread_mutexattr_init(&attr)) { uwsgi_log("unable to allocate mutexattr structure\n"); exit(1); } if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { uwsgi_log("unable to share mutex\n"); exit(1); } #ifdef EOWNERDEAD #ifndef PTHREAD_MUTEX_ROBUST #define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP #define pthread_mutexattr_setrobust pthread_mutexattr_setrobust_np #define pthread_mutex_consistent pthread_mutex_consistent_np #endif if (uwsgi_pthread_robust_mutexes_enabled) { int ret; if ((ret = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) != 0) { switch (ret) { case ENOTSUP: // PTHREAD_PRIO_INHERIT will only prevent // priority inversion when SCHED_FIFO or // SCHED_RR is used, so this is non-fatal and // also currently unsupported on musl. break; default: uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n"); exit(1); } } if (pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST)) { uwsgi_log("unable to make the mutex 'robust'\n"); exit(1); } } #endif if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) { #ifdef EOWNERDEAD if (uwsgi_pthread_robust_mutexes_enabled) { uwsgi_log("!!! it looks like your kernel does not support pthread robust mutexes !!!\n"); uwsgi_log("!!! falling back to standard pthread mutexes !!!\n"); uwsgi_pthread_robust_mutexes_enabled = 0; pthread_mutexattr_destroy(&attr); goto retry; } #endif uwsgi_log("unable to initialize mutex\n"); exit(1); } pthread_mutexattr_destroy(&attr); #ifdef EOWNERDEAD if (!uwsgi_pthread_robust_mutexes_enabled) { uli->can_deadlock = 1; } #else uli->can_deadlock = 1; #endif return uli; }
_PUBLIC_ bool tdb_runtime_check_for_robust_mutexes(void) { void *ptr; pthread_mutex_t *m; pthread_mutexattr_t ma; int ret = 1; int pipe_down[2] = { -1, -1 }; int pipe_up[2] = { -1, -1 }; ssize_t nread; char c = 0; bool ok; int status; static bool initialized; if (initialized) { return tdb_mutex_locking_cached; } initialized = true; ok = tdb_mutex_locking_supported(); if (!ok) { return false; } tdb_mutex_locking_cached = false; ptr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1 /* fd */, 0); if (ptr == MAP_FAILED) { return false; } m = (pthread_mutex_t *)ptr; ret = pipe(pipe_down); if (ret != 0) { goto cleanup_mmap; } ret = pipe(pipe_up); if (ret != 0) { goto cleanup_pipe; } ret = pthread_mutexattr_init(&ma); if (ret != 0) { goto cleanup_pipe; } ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutex_init(m, &ma); if (ret != 0) { goto cleanup_ma; } tdb_robust_mutext_old_handler = signal(SIGCHLD, tdb_robust_mutex_handler); tdb_robust_mutex_pid = fork(); if (tdb_robust_mutex_pid == 0) { size_t nwritten; close(pipe_down[1]); close(pipe_up[0]); ret = pthread_mutex_lock(m); nwritten = write(pipe_up[1], &ret, sizeof(ret)); if (nwritten != sizeof(ret)) { exit(1); } if (ret != 0) { exit(1); } nread = read(pipe_down[0], &c, 1); if (nread != 1) { exit(1); } /* leave locked */ exit(0); } if (tdb_robust_mutex_pid == -1) { goto cleanup_sig_child; } close(pipe_down[0]); pipe_down[0] = -1; close(pipe_up[1]); pipe_up[1] = -1; nread = read(pipe_up[0], &ret, sizeof(ret)); if (nread != sizeof(ret)) { goto cleanup_child; } ret = pthread_mutex_trylock(m); if (ret != EBUSY) { if (ret == 0) { pthread_mutex_unlock(m); } goto cleanup_child; } if (write(pipe_down[1], &c, 1) != 1) { goto cleanup_child; } nread = read(pipe_up[0], &c, 1); if (nread != 0) { goto cleanup_child; } while (tdb_robust_mutex_pid > 0) { pid_t pid; errno = 0; pid = waitpid(tdb_robust_mutex_pid, &status, 0); if (pid == tdb_robust_mutex_pid) { tdb_robust_mutex_pid = -1; break; } if (pid == -1 && errno != EINTR) { goto cleanup_child; } } signal(SIGCHLD, tdb_robust_mutext_old_handler); ret = pthread_mutex_trylock(m); if (ret != EOWNERDEAD) { if (ret == 0) { pthread_mutex_unlock(m); } goto cleanup_m; } ret = pthread_mutex_consistent(m); if (ret != 0) { goto cleanup_m; } ret = pthread_mutex_trylock(m); if (ret != EDEADLK) { pthread_mutex_unlock(m); goto cleanup_m; } ret = pthread_mutex_unlock(m); if (ret != 0) { goto cleanup_m; } tdb_mutex_locking_cached = true; goto cleanup_m; cleanup_child: while (tdb_robust_mutex_pid > 0) { pid_t pid; kill(tdb_robust_mutex_pid, SIGKILL); errno = 0; pid = waitpid(tdb_robust_mutex_pid, &status, 0); if (pid == tdb_robust_mutex_pid) { tdb_robust_mutex_pid = -1; break; } if (pid == -1 && errno != EINTR) { break; } } cleanup_sig_child: signal(SIGCHLD, tdb_robust_mutext_old_handler); cleanup_m: pthread_mutex_destroy(m); cleanup_ma: pthread_mutexattr_destroy(&ma); cleanup_pipe: if (pipe_down[0] != -1) { close(pipe_down[0]); } if (pipe_down[1] != -1) { close(pipe_down[1]); } if (pipe_up[0] != -1) { close(pipe_up[0]); } if (pipe_up[1] != -1) { close(pipe_up[1]); } cleanup_mmap: munmap(ptr, sizeof(pthread_mutex_t)); return tdb_mutex_locking_cached; }
int main() { pthread_t to, ti; pthread_mutexattr_t ma; assert(pthread_mutexattr_init(&ma) == 0); assert(pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST) == 0); /* Default (NORMAL) type */ lockCount = 0; assert(pthread_mutex_init(&mutex, &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, NULL) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 2); assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE); assert(pthread_mutex_destroy(&mutex) == 0); /* NORMAL type */ lockCount = 0; assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_NORMAL) == 0); assert(pthread_mutex_init(&mutex, &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, NULL) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 2); assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE); assert(pthread_mutex_destroy(&mutex) == 0); /* ERRORCHECK type */ lockCount = 0; assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK) == 0); assert(pthread_mutex_init(&mutex, &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, NULL) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 2); assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE); assert(pthread_mutex_destroy(&mutex) == 0); /* RECURSIVE type */ lockCount = 0; assert(pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE) == 0); assert(pthread_mutex_init(&mutex, &ma) == 0); assert(pthread_create(&to, NULL, owner, NULL) == 0); Sleep(100); assert(pthread_create(&ti, NULL, inheritor, NULL) == 0); assert(pthread_join(to, NULL) == 0); assert(pthread_join(ti, NULL) == 0); assert(lockCount == 2); assert(pthread_mutex_lock(&mutex) == ENOTRECOVERABLE); assert(pthread_mutex_destroy(&mutex) == 0); assert(pthread_mutexattr_destroy(&ma) == 0); return 0; }
/*----------------------------------------------------------------------------*/ static udps_err_t udps_lock_init(void) { int smfd; pthread_mutexattr_t mattr; int rc; /* If the shared memory object already exists, unlink it. */ shm_unlink(UDPS_SM_OBJ_NAME); /* Create a new share memory object. * O_RDWR = Open for reading and writing. * O_CREAT = Create the shared memory object if it does not exist. * O_EXCL = If the given name already exists, return an error. * S_IRUSR = User has read permission. * S_IWUSR = User has write permission. */ LOG_SRV(UDPS_LOG_DEBUG, ("Creating shared memory object...")); smfd = shm_open(UDPS_SM_OBJ_NAME, (O_RDWR|O_CREAT|O_EXCL|O_TRUNC), (S_IRUSR|S_IWUSR)); if(smfd < 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not create share memory object: " "%s (%d)", strerror(errno), errno)); return UDPS_ERR_SMEM_OBJ_CREATE; } rc = ftruncate(smfd, sizeof(pthread_mutex_t)); if(rc != 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not truncate share memory object: " "%s (%d)", strerror(errno), errno)); return UDPS_ERR_SMEM_OBJ_TRUNC; } /* Create a new mapping in the virtual address space. * NULL = The kernel chooses the address at which to create the * mapping. * PROT_READ = Pages may be read. * PROT_WRITE = Pages may be written. * MAP_SHARED = Updates to the mapping are visible to other processes * that map this file. */ LOG_SRV(UDPS_LOG_DEBUG, ("Creating shared memory mapping...")); srv.mptr = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), (PROT_READ|PROT_WRITE), MAP_SHARED, smfd, 0); if(srv.mptr == MAP_FAILED) { LOG_SRV(UDPS_LOG_EMERG, ("Could not create share memory mapping: " "%s (%d)", strerror(errno), errno)); close(smfd); return UDPS_ERR_SMEM_MAP_CREATE; } /* Close shared memory object. */ LOG_SRV(UDPS_LOG_DEBUG, ("Closing shared memory object...")); if(close(smfd) != 0) { LOG_SRV(UDPS_LOG_WARNING, ("Could not close shared memory object: " "%s (%d)", strerror(errno), errno)); } /* Create processes controller mutex. * PTHREAD_PROCESS_SHARED = permit a mutex to be operated upon by any thread * that has access to the memory where the mutex is * allocated, even if the mutex is allocated in * memory that is shared by multiple processes. * PTHREAD_MUTEX_ROBUST = If the process containing the owning thread of a * robust mutex terminates while holding the mutex * lock, the next thread that acquires the mutex * shall be notified about the termination by the * return value [EOWNERDEAD] from the locking * function. */ LOG_SRV(UDPS_LOG_DEBUG, ("Creating processes controler mutex...")); rc = pthread_mutexattr_init(&mattr); if(rc != 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not create pthread mutex attribute: " "%d", rc)); return UDPS_ERR_SMEM_ATTR_CREATE; } rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); if(rc != 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not set pthread mutex attribute as " "shared: %d", rc)); pthread_mutexattr_destroy(&mattr); return UDPS_ERR_SMEM_ATTR_SET; } rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); if(rc != 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not set pthread mutex attribute as " "robust: %d", rc)); pthread_mutexattr_destroy(&mattr); return UDPS_ERR_SMEM_ATTR_SET; } rc = pthread_mutex_init(srv.mptr, &mattr); if(rc != 0) { LOG_SRV(UDPS_LOG_EMERG, ("Could not initialize pthread mutex: %d", rc)); pthread_mutexattr_destroy(&mattr); return UDPS_ERR_SMEM_MUTEX_INIT; } /* Close unneeded pthread mutex attribute. */ LOG_SRV(UDPS_LOG_DEBUG, ("Destroying unneeded pthread mutex attribute...")); rc = pthread_mutexattr_destroy(&mattr); if(rc != 0) { LOG_SRV(UDPS_LOG_WARNING, ("Could not close pthread mutex attribute: " "%d", rc)); } return UDPS_OK; }
static bool tdb_mutex_locking_supported(void) { pthread_mutexattr_t ma; pthread_mutex_t m; int ret; static bool initialized; if (initialized) { return tdb_mutex_locking_cached; } initialized = true; ret = pthread_mutexattr_init(&ma); if (ret != 0) { return false; } ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutex_init(&m, &ma); if (ret != 0) { goto cleanup_ma; } ret = pthread_mutex_lock(&m); if (ret != 0) { goto cleanup_m; } /* * This makes sure we have real mutexes * from a threading library instead of just * stubs from libc. */ ret = pthread_mutex_lock(&m); if (ret != EDEADLK) { goto cleanup_lock; } ret = pthread_mutex_unlock(&m); if (ret != 0) { goto cleanup_m; } tdb_mutex_locking_cached = true; goto cleanup_m; cleanup_lock: pthread_mutex_unlock(&m); cleanup_m: pthread_mutex_destroy(&m); cleanup_ma: pthread_mutexattr_destroy(&ma); return tdb_mutex_locking_cached; }
int test_benchtest2(void) #endif { assert(pthread_mutexattr_init(&ma) == 0); printf( "=============================================================================\n"); printf( "\nLock plus unlock on a locked mutex.\n"); printf("%ld iterations, four locks/unlocks per iteration.\n\n", ITERATIONS); printf( "%-45s %15s %15s\n", "Test", "Total(msec)", "average(usec)"); printf( "-----------------------------------------------------------------------------\n"); /* * Time the loop overhead so we can subtract it from the actual test times. */ running = 1; assert(pthread_create(&worker, NULL, overheadThread, NULL) == 0); TESTSTART; sched_yield(); sched_yield(); TESTSTOP; running = 0; assert(pthread_join(worker, NULL) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; overHeadMilliSecs = durationMilliSecs; InitializeCriticalSection(&cs1); InitializeCriticalSection(&cs2); EnterCriticalSection(&cs1); EnterCriticalSection(&cs2); running = 1; assert(pthread_create(&worker, NULL, CSThread, NULL) == 0); TESTSTART; LeaveCriticalSection(&cs1); sched_yield(); LeaveCriticalSection(&cs2); EnterCriticalSection(&cs1); EnterCriticalSection(&cs2); TESTSTOP; running = 0; LeaveCriticalSection(&cs2); LeaveCriticalSection(&cs1); assert(pthread_join(worker, NULL) == 0); DeleteCriticalSection(&cs2); DeleteCriticalSection(&cs1); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Simple Critical Section", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS / 4 ); old_mutex_use = OLD_WIN32CS; assert(old_mutex_init(&ox1, NULL) == 0); assert(old_mutex_init(&ox2, NULL) == 0); assert(old_mutex_lock(&ox1) == 0); assert(old_mutex_lock(&ox2) == 0); running = 1; assert(pthread_create(&worker, NULL, oldThread, NULL) == 0); TESTSTART; (void) old_mutex_unlock(&ox1); sched_yield(); (void) old_mutex_unlock(&ox2); (void) old_mutex_lock(&ox1); (void) old_mutex_lock(&ox2); TESTSTOP; running = 0; assert(old_mutex_unlock(&ox1) == 0); assert(old_mutex_unlock(&ox2) == 0); assert(pthread_join(worker, NULL) == 0); assert(old_mutex_destroy(&ox2) == 0); assert(old_mutex_destroy(&ox1) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Critical Section (WNT)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS / 4); old_mutex_use = OLD_WIN32MUTEX; assert(old_mutex_init(&ox1, NULL) == 0); assert(old_mutex_init(&ox2, NULL) == 0); assert(old_mutex_lock(&ox1) == 0); assert(old_mutex_lock(&ox2) == 0); running = 1; assert(pthread_create(&worker, NULL, oldThread, NULL) == 0); TESTSTART; (void) old_mutex_unlock(&ox1); sched_yield(); (void) old_mutex_unlock(&ox2); (void) old_mutex_lock(&ox1); (void) old_mutex_lock(&ox2); TESTSTOP; running = 0; assert(old_mutex_unlock(&ox1) == 0); assert(old_mutex_unlock(&ox2) == 0); assert(pthread_join(worker, NULL) == 0); assert(old_mutex_destroy(&ox2) == 0); assert(old_mutex_destroy(&ox1) == 0); durationMilliSecs = GetDurationMilliSecs(currSysTimeStart, currSysTimeStop) - overHeadMilliSecs; printf( "%-45s %15ld %15.3f\n", "Old PT Mutex using a Win32 Mutex (W9x)", durationMilliSecs, (float) durationMilliSecs * 1E3 / ITERATIONS / 4); printf( ".............................................................................\n"); /* * Now we can start the actual tests */ #ifdef PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( ".............................................................................\n"); pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); #ifdef PTW32_MUTEX_TYPES runTest("PTHREAD_MUTEX_DEFAULT (Robust)", PTHREAD_MUTEX_DEFAULT); runTest("PTHREAD_MUTEX_NORMAL (Robust)", PTHREAD_MUTEX_NORMAL); runTest("PTHREAD_MUTEX_ERRORCHECK (Robust)", PTHREAD_MUTEX_ERRORCHECK); runTest("PTHREAD_MUTEX_RECURSIVE (Robust)", PTHREAD_MUTEX_RECURSIVE); #else runTest("Non-blocking lock", 0); #endif printf( "=============================================================================\n"); /* * End of tests. */ pthread_mutexattr_destroy(&ma); return 0; }
int main(int argc, const char **argv) { pthread_mutexattr_t ma; pthread_mutex_t *mutex; int fd, ret, i; pid_t pid; void *addr; int num_children; int priority = PRIO_NORMAL; if (argc < 3 || argc > 4) { fprintf(stderr, "Usage: %s <file> <n> [0|1|2]\n", argv[0]); fprintf(stderr, " %s <file> debug\n", argv[0]); exit(1); } if (argc == 4) { priority = atoi(argv[3]); } if (priority == PRIO_REALTIME) { set_realtime(); } else if (priority == PRIO_NICE_20) { high_priority(); } fd = open(argv[1], O_CREAT|O_RDWR, 0600); if (fd == -1) { fprintf(stderr, "open failed\n"); exit(1); } ret = lseek(fd, 0, SEEK_SET); if (ret != 0) { fprintf(stderr, "lseek failed\n"); exit(1); } ret = ftruncate(fd, sizeof(pthread_mutex_t)); if (ret != 0) { fprintf(stderr, "ftruncate failed\n"); exit(1); } addr = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE, fd, 0); if (addr == NULL) { fprintf(stderr, "mmap failed\n"); exit(1); } mutex = (pthread_mutex_t *)addr; if (strcmp(argv[2], "debug") == 0) { ret = pthread_mutex_trylock(mutex); if (ret == EOWNERDEAD) { ret = pthread_mutex_consistent(mutex); if (ret == 0) { pthread_mutex_unlock(mutex); } } else if (ret == EBUSY) { printf("pid=%u\n", mutex->__data.__owner); } else if (ret == 0) { pthread_mutex_unlock(mutex); } exit(0); } ret = pthread_mutexattr_init(&ma); if (ret != 0) { fprintf(stderr, "pthread_mutexattr_init failed\n"); exit(1); } ret = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { fprintf(stderr, "pthread_mutexattr_settype failed\n"); exit(1); } ret = pthread_mutexattr_setpshared(&ma, PTHREAD_PROCESS_SHARED); if (ret != 0) { fprintf(stderr, "pthread_mutexattr_setpshared failed\n"); exit(1); } ret = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); if (ret != 0) { fprintf(stderr, "pthread_mutexattr_setrobust failed\n"); exit(1); } ret = pthread_mutex_init(mutex, &ma); if (ret != 0) { fprintf(stderr, "pthread_mutex_init failed\n"); exit(1); } ret = pthread_mutex_lock(mutex); if (ret != 0) { fprintf(stderr, "pthread_mutex_lock failed\n"); exit(1); } setpgid(0, 0); fprintf(stderr, "Creating children\n"); num_children = atoi(argv[2]); for (i=0; i<num_children; i++) { pid = fork(); if (pid < 0) { fprintf(stderr, "fork() failed\n"); exit(1); } if (pid == 0) { close(fd); run_child(argv[1]); exit(1); } } fprintf(stderr, "Waiting for children\n"); ret = pthread_mutex_unlock(mutex); if (ret != 0) { fprintf(stderr, "pthread_mutex_unlock failed\n"); exit(1); } for (i=0; i<num_children; i++) { int status; pid = waitpid(-1, &status, 0); if (pid <= 0) { fprintf(stderr, "waitpid() failed\n"); } } close(fd); unlink(argv[1]); exit(0); }
am_shm_t *am_shm_create(const char *name, size_t usize) { struct mem_pool *pool = NULL; size_t size; char opened = AM_FALSE; void *area = NULL; am_shm_t *ret = NULL; #ifdef _WIN32 char dll_path[AM_URI_SIZE]; DWORD error = 0; HMODULE hm = NULL; void *caller = _ReturnAddress(); #else int fdflags; int error = 0; #endif ret = calloc(1, sizeof(am_shm_t)); if (ret == NULL) return NULL; #ifdef _WIN32 if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) caller, &hm) && GetModuleFileNameA(hm, dll_path, sizeof(dll_path) - 1) > 0) { PathRemoveFileSpecA(dll_path); strcat(dll_path, FILE_PATH_SEP); snprintf(ret->name[0], sizeof(ret->name[0]), AM_GLOBAL_PREFIX"%s_l", name); /* mutex/semaphore */ snprintf(ret->name[1], sizeof(ret->name[1]), AM_GLOBAL_PREFIX"%s_s", name); /* shared memory name */ snprintf(ret->name[2], sizeof(ret->name[2]), "%s.."FILE_PATH_SEP"log"FILE_PATH_SEP"%s_f", dll_path, name); /* shared memory file name */ snprintf(ret->name[3], sizeof(ret->name[3]), AM_GLOBAL_PREFIX"%s_sz", name); /* shared memory name for global_size */ } else { ret->error = AM_NOT_FOUND; return ret; } #else snprintf(ret->name[0], sizeof(ret->name[0]), "/%s_l", name); /* mutex/semaphore */ snprintf(ret->name[1], sizeof(ret->name[1]), #ifdef __sun "/%s_s" #else "%s_s" #endif , name); /* shared memory name */ #endif size = page_size(usize + SIZEOF_mem_pool); /* need at least the size of the mem_pool header */ #ifdef _WIN32 ret->h[0] = CreateMutexA(NULL, TRUE, ret->name[0]); error = GetLastError(); if (ret->h[0] != NULL && error == ERROR_ALREADY_EXISTS) { do { error = WaitForSingleObject(ret->h[0], INFINITE); } while (error == WAIT_ABANDONED); } else { if (error == ERROR_ACCESS_DENIED) { ret->h[0] = OpenMutexA(SYNCHRONIZE, FALSE, ret->name[0]); } if (ret->h[0] == NULL) { ret->error = error; return ret; } } ret->h[1] = CreateFileA(ret->name[2], GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); error = GetLastError(); if (ret->h[1] == INVALID_HANDLE_VALUE && error == ERROR_FILE_EXISTS) { ret->h[1] = CreateFileA(ret->name[2], GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); error = GetLastError(); if (ret->h[1] != INVALID_HANDLE_VALUE) { opened = AM_TRUE; size = GetFileSize(ret->h[1], NULL); } } if (ret->h[1] == INVALID_HANDLE_VALUE || error != 0) { CloseHandle(ret->h[0]); ret->error = error; am_shm_unlock(ret); return ret; } if (!opened) { ret->h[2] = CreateFileMappingA(ret->h[1], NULL, PAGE_READWRITE, 0, (DWORD) size, ret->name[1]); error = GetLastError(); } else { ret->h[2] = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, ret->name[1]); error = GetLastError(); if (ret->h[2] == NULL && error == ERROR_FILE_NOT_FOUND) { ret->h[2] = CreateFileMappingA(ret->h[1], NULL, PAGE_READWRITE, 0, (DWORD) size, ret->name[1]); error = GetLastError(); } } if (ret->h[2] == NULL || error != 0) { CloseHandle(ret->h[0]); CloseHandle(ret->h[1]); ret->error = error; am_shm_unlock(ret); return ret; } area = MapViewOfFile(ret->h[2], FILE_MAP_ALL_ACCESS, 0, 0, 0); error = GetLastError(); if (area == NULL || (error != 0 && error != ERROR_ALREADY_EXISTS)) { CloseHandle(ret->h[0]); CloseHandle(ret->h[1]); CloseHandle(ret->h[2]); ret->error = error; am_shm_unlock(ret); return ret; } ret->h[3] = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD) sizeof(size_t), ret->name[3]); if (ret->h[3] == NULL) { ret->error = GetLastError(); CloseHandle(ret->h[0]); CloseHandle(ret->h[1]); CloseHandle(ret->h[2]); am_shm_unlock(ret); return ret; } ret->global_size = MapViewOfFile(ret->h[3], FILE_MAP_ALL_ACCESS, 0, 0, 0); if (ret->global_size == NULL) { ret->error = GetLastError(); CloseHandle(ret->h[0]); CloseHandle(ret->h[1]); CloseHandle(ret->h[2]); CloseHandle(ret->h[3]); am_shm_unlock(ret); return ret; } *(ret->global_size) = ret->local_size = size; #else ret->lock = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); if (ret->lock == MAP_FAILED) { ret->error = errno; return ret; } else { pthread_mutexattr_t attr; pthread_mutex_t *lock = (pthread_mutex_t *) ret->lock; pthread_mutexattr_init(&attr); pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #if defined(__sun) #if defined(__SunOS_5_10) #if defined(_POSIX_THREAD_PRIO_INHERIT) pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); #endif #else pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); #endif #endif #if defined(LINUX) pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); #endif pthread_mutex_init(lock, &attr); pthread_mutexattr_destroy(&attr); } ret->global_size = mmap(NULL, sizeof(size_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); if (ret->global_size == MAP_FAILED) { ret->error = errno; return ret; } *(ret->global_size) = ret->local_size = size; am_shm_lock(ret); ret->fd = shm_open(ret->name[1], O_CREAT | O_EXCL | O_RDWR, 0666); error = errno; if (ret->fd == -1 && error != EEXIST) { munmap(ret->lock, sizeof(pthread_mutex_t)); ret->error = error; am_shm_unlock(ret); return ret; } if (ret->fd == -1) { ret->fd = shm_open(ret->name[1], O_RDWR, 0666); error = errno; if (ret->fd == -1) { munmap(ret->lock, sizeof(pthread_mutex_t)); ret->error = error; am_shm_unlock(ret); return ret; } /* reset FD_CLOEXEC */ fdflags = fcntl(ret->fd, F_GETFD); fdflags &= ~FD_CLOEXEC; fcntl(ret->fd, F_SETFD, fdflags); /* try with just a header */ area = mmap(NULL, SIZEOF_mem_pool, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0); if (area == MAP_FAILED) { ret->error = errno; am_shm_unlock(ret); return ret; } size = ((struct mem_pool *) area)->size; if (munmap(area, SIZEOF_mem_pool) == -1) { ret->error = errno; am_shm_unlock(ret); return ret; } area = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0); if (area == MAP_FAILED) { ret->error = errno; am_shm_unlock(ret); return ret; } opened = AM_TRUE; } else { /* reset FD_CLOEXEC */ fdflags = fcntl(ret->fd, F_GETFD); fdflags &= ~FD_CLOEXEC; fcntl(ret->fd, F_SETFD, fdflags); if (ftruncate(ret->fd, size) == -1) { ret->error = errno; am_shm_unlock(ret); return ret; } area = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ret->fd, 0); if (area == MAP_FAILED) { ret->error = errno; am_shm_unlock(ret); return ret; } } #endif ret->init = !opened; pool = (struct mem_pool *) area; if (ret->init) { struct mem_chunk *e = (struct mem_chunk *) ((char *) pool + SIZEOF_mem_pool); pool->size = size; pool->user_offset = 0; pool->open = 1; pool->resize = 0; /* add all available (free) space as one chunk in a freelist */ e->used = 0; e->usize = 0; e->size = pool->size - SIZEOF_mem_pool; e->lh.next = e->lh.prev = 0; /* update head prev/next pointers */ pool->lh.next = pool->lh.prev = AM_GET_OFFSET(pool, e); } else { if (pool->user_offset > 0) { ret->user = AM_GET_POINTER(pool, pool->user_offset); } pool->open++; } ret->pool = pool; ret->error = 0; am_shm_unlock(ret); return ret; }