int mutex_try_enter (dk_mutex_t *mtx) { #ifndef MTX_DEBUG #if HAVE_SPINLOCK if (MUTEX_TYPE_SPIN == mtx->mtx_type) return pthread_spin_trylock (&mtx->l.spinl) == TRYLOCK_SUCCESS ? 1 : 0; else #endif return pthread_mutex_trylock ((pthread_mutex_t *) &mtx->mtx_mtx) == TRYLOCK_SUCCESS ? 1 : 0; #else if ( #if HAVE_SPINLOCK MUTEX_TYPE_SPIN == mtx->mtx_type ? pthread_spin_trylock (&mtx->l.spinl) == TRYLOCK_SUCCESS : #endif pthread_mutex_trylock ((pthread_mutex_t*) &mtx->mtx_mtx) == TRYLOCK_SUCCESS) { assert (mtx->mtx_owner == NULL); mtx->mtx_owner = thread_current (); return 1; } return 0; #endif }
int main() { pthread_t thread_id; int seconds = 3; int rc; printf("will init\n"); pthread_spin_init(&lock, -1); printf("1\n"); pthread_spin_lock(&lock); sleep(1); printf("2\n"); rc = pthread_create(&thread_id, NULL, g_start_timer, (void *) &seconds); if (rc) printf("=== Failed to create thread\n"); printf("4\n"); pthread_spin_unlock(&lock); sleep(1); if(0 != pthread_spin_trylock(&lock)) { printf("6 failed to get trylock, as expected\n"); } #if 0 #endif pthread_join(thread_id, NULL); printf("=== End of Program - all threads in ===\n"); return 0; }
/* Try to attain a lock. Do not block! Returns true if the lock was attained. */ PUBLIC bool mprTrySpinLock(MprSpin *lock) { int rc; if (lock == 0) return 0; #if USE_MPR_LOCK mprTryLock(&lock->cs); #elif MACOSX rc = !OSSpinLockTry(&lock->cs); #elif ME_UNIX_LIKE && ME_COMPILER_HAS_SPINLOCK rc = pthread_spin_trylock(&lock->cs) != 0; #elif ME_UNIX_LIKE rc = pthread_mutex_trylock(&lock->cs) != 0; #elif ME_WIN_LIKE rc = (lock->freed) ? 0 : (TryEnterCriticalSection(&lock->cs) == 0); #elif VXWORKS rc = semTake(lock->cs, NO_WAIT) != OK; #endif #if ME_DEBUG && COSTLY if (rc == 0) { assert(lock->owner != mprGetCurrentOsThread()); lock->owner = mprGetCurrentOsThread(); } #endif return (rc) ? 0 : 1; }
void node_del_data_event(struct node *node) { int ret; log_error("%s: del data event for node %d", __func__, node->id); ret = pthread_spin_trylock(&node->spinlock); if(ret != 0) { log_error("%s: del data event get lock failed", __func__); return; } if(node->data_event == NULL) { log_error("%s: null data_event for node %d, cancel", __func__, node->id); goto err; } shutdown(node->dfd, SHUT_RDWR); sock_close(node->dfd); node->dfd = -1; node->data_conn_state = NODE_DFD_DISCONNECTED; event_free(node->data_event); node->data_event = NULL; pthread_spin_unlock(&node->spinlock); clean_packet_queue(node->data_q); node_disconnect(node); return; err: pthread_spin_unlock(&node->spinlock); }
bool locker::try_lock() { #ifdef ACL_HAS_SPINLOCK if (spinlock_) { if (pthread_spin_trylock(spinlock_) != 0) return false; } else #endif if (mutex_) { if (acl_pthread_mutex_trylock(mutex_) != 0) return false; } if (fHandle_ == ACL_FILE_INVALID) return true; int operation = ACL_FLOCK_OP_EXCLUSIVE | ACL_FLOCK_OP_NOWAIT; if (acl_myflock(fHandle_, ACL_FLOCK_STYLE_FCNTL, operation) == 0) return true; if (mutex_) acl_assert(acl_pthread_mutex_unlock(mutex_) == 0); return false; }
static void * func(void * arg) { assert(pthread_spin_trylock(&lock) == EBUSY); washere = 1; return 0; }
// funzione del thread void *do_something(long int who_i_am) { int i; // finche' non vuoi uscire while (!wanna_exit) { i=rand()%9+1; // genera un intervallo casuale di tempo printf("Thread %ld: going to sleep for %d sec...\n",who_i_am,i); // se devi uscire if (wanna_exit) { printf("Thread %ld: exit...\n",who_i_am); // esci break; } // dormi per un intervallo casuale sleep(i); // se ti hanno svegliato per uscire if (wanna_exit) { printf("Thread %ld: exit...\n",who_i_am); // esci break; } // prova se lo spinlock e' libero if (pthread_spin_trylock(&spinlock)) { // in caso contrario avvisa printf("Thread %ld: wait for the spinlock...\n",who_i_am); // e aspetta pthread_spin_lock(&spinlock); } // da qui si ha il possesso dello spinlock // genera un intervallo casuale i=rand()%9+1; // esci se devi if (wanna_exit) { // non prima di aver sbloccato il mutex per l'altro processo pthread_spin_unlock(&spinlock); printf("Thread %ld: exit...\n",who_i_am); break; } // avvisi vari printf("Thread %ld: spinlock obtained and now wait for %d sec...\n",who_i_am,i); // dormi sleep(i); // se ti hanno svegliato per uscire if (wanna_exit) { // sblocca il mutex pthread_spin_unlock(&spinlock); printf("Thread %ld: exit...\n",who_i_am); // ed esci break; } // altrimenti rilascia il mutex printf("Thread %ld: unlock spinlock...\n",who_i_am); pthread_spin_unlock(&spinlock); } return NULL; }
int devil_spinlock_trylock(devil_spinlock_t* spinlock) { int ret = pthread_spin_trylock(spinlock); if (0 != ret && EBUSY != ret && EAGAIN != ret) abort(); return ret; }
bool spinlock_trylock(spinlock_t *lock) { const int err = pthread_spin_trylock(lock); if (err == 0) return true; else if (err == EBUSY) return false; else { error("spinlock error: %s", errno_error(err)); return false; } }
void *reader( void *ptr) { struct timespec start, end; int tid = *((int *) ptr); uint64_t seed = 0xdeadbeef + tid; int sum = 0, i; /** < The node and lock to use in an iteration */ int node_id, lock_id; /** < Total number of iterations (for measurement) */ int num_iters = 0; clock_gettime(CLOCK_REALTIME, &start); while(1) { if(num_iters == ITERS_PER_MEASUREMENT) { clock_gettime(CLOCK_REALTIME, &end); double seconds = (end.tv_sec - start.tv_sec) + (double) (end.tv_nsec - start.tv_nsec) / GHZ_CPS; printf("Reader thread %d: rate = %.2f M/s. Sum = %d\n", tid, num_iters / (1000000 * seconds), sum); num_iters = 0; clock_gettime(CLOCK_REALTIME, &start); } node_id = fastrand(&seed) & NUM_NODES_; lock_id = node_id & NUM_LOCKS_; #if USE_SKIP == 1 while(pthread_spin_trylock(&locks[lock_id].lock) == EBUSY) { lock_id = (lock_id + 1) & NUM_LOCKS_; } #else pthread_spin_lock(&locks[lock_id].lock); /** < Critical section begin */ if(nodes[node_id].b != nodes[node_id].a + 1) { red_printf("Invariant violated\n"); } #endif for(i = 0; i < WRITER_COMPUTE; i ++) { sum += CityHash32((char *) &nodes[node_id].a, 4); sum += CityHash32((char *) &nodes[node_id].b, 4); } /** < Critical section end */ pthread_spin_unlock(&locks[lock_id].lock); num_iters ++; } }
int _starpu_spin_trylock(starpu_spinlock_t *lock) { #ifdef HAVE_PTHREAD_SPIN_LOCK int ret = pthread_spin_trylock(&lock->lock); STARPU_ASSERT(!ret || (ret == EBUSY)); return ret; #else uint32_t prev; prev = STARPU_TEST_AND_SET(&lock->taken, 1); return (prev == 0)?0:EBUSY; #endif }
bool try_lock() { int ret; do { ret = pthread_spin_trylock(&spin); } while (OXT_UNLIKELY(ret == EINTR)); if (ret == 0) { return true; } else if (ret == EBUSY) { return false; } else { throw boost::thread_resource_error(ret, "Cannot lock spin lock"); } }
rtems_task SpinlockThread(rtems_task_argument arg) { int status; puts( "pthread_spin_trylock( &Spinlock ) -- EBUSY" ); status = pthread_spin_trylock( &Spinlock ); rtems_test_assert( status == EBUSY ); puts( "pthread_spin_unlock( &Spinlock ) -- EPERM" ); status = pthread_spin_unlock( &Spinlock ); rtems_test_assert( status == EPERM ); rtems_task_delete( RTEMS_SELF ); }
static void faultd_signal_handler__(int signal, siginfo_t* siginfo, void* context) { int rv; /* * Make sure we syncronize properly with other threads that * may *also* be faulting */ rv = pthread_spin_trylock(&thread_lock__); if (rv == EBUSY) { sigset_t mask; sigemptyset(&mask); pselect(0, NULL, NULL, NULL, NULL, &mask); } /* * Generate our fault information. */ faultd_info__.pid = getpid(); faultd_info__.tid = 0; faultd_info__.signal = signal; faultd_info__.signal_code = siginfo->si_code; faultd_info__.fault_address = siginfo->si_addr; faultd_info__.last_errno = errno; faultd_info__.backtrace_size = signal_backtrace__(faultd_info__.backtrace, AIM_ARRAYSIZE(faultd_info__.backtrace), context, 0); faultd_info__.backtrace_symbols = (void*)1; if(faultd_client__) { faultd_client_write(faultd_client__, &faultd_info__); } if(localfd__ >= 0) { char* signame = strsignal(faultd_info__.signal); char* nl = "\n"; write(localfd__, signame, strlen(signame)+1); write(localfd__, nl, 2); backtrace_symbols_fd(faultd_info__.backtrace, faultd_info__.backtrace_size, localfd__); } /* * Unlock spinlock, in case this signal wasn't fatal */ pthread_spin_unlock(&thread_lock__); }
Bool HawkSpinLock::TryLock(const AString& sFile,Int32 iLine) { HawkAssert(m_pSpinLock); if (pthread_spin_trylock((pthread_spinlock_t*)m_pSpinLock) == HAWK_OK) { #ifdef _DEBUG m_bLocked = true; m_sFile = sFile; m_iLine = iLine; m_iThread = HawkOSOperator::GetThreadId(); #endif return true; } return false; }
int main() { pthread_t child_thread; if(pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE) != 0) { printf("main: Error at pthread_spin_init()\n"); return PTS_UNRESOLVED; } printf("main: attempt to trylock\n"); /* We should get the lock */ if(pthread_spin_trylock(&spinlock) != 0) { printf("Test FAILED: main cannot get spin lock when no one owns the lock\n"); return PTS_FAIL; } printf("main: acquired spin lock\n"); thread_state = NOT_CREATED_THREAD; printf("main: create thread\n"); if(pthread_create(&child_thread, NULL, fn_chld, NULL) != 0) { printf("main: Error creating child thread\n"); return PTS_UNRESOLVED; } /* Wait for thread to end execution */ pthread_join(child_thread, NULL); /* Check the return code of pthread_spin_trylock */ if(rc != EBUSY) { printf("Test FAILED: pthread_spin_trylock should return EBUSY, instead got error code:%d\n" , rc); return PTS_FAIL; } printf("thread: correctly returned EBUSY on trylock\n"); printf("Test PASSED\n"); return PTS_PASS; }
int core_lock_trylock(struct core_lock *self) { #if defined(CORE_LOCK_USE_COMPARE_AND_SWAP) int old_value = 0; int new_value = 1; if (core_atomic_compare_and_swap_int(&self->lock, old_value, new_value) == old_value) { /* successful */ return CORE_LOCK_SUCCESS; } /* not successful */ return CORE_LOCK_ERROR; #elif defined(CORE_LOCK_USE_SPIN_LOCK) return pthread_spin_trylock(&self->lock); #elif defined(CORE_LOCK_USE_MUTEX) return pthread_mutex_trylock(&self->lock); #endif }
// funzione realtiva allo spinlock void *do_something(long int who_i_am) { int i; int dummy; // imposta la cancellazione asincrona pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&dummy); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&dummy); // aspetta che pure l'altro thread l'abbia fatto pthread_barrier_wait(&pbarrier); // sblocca il segnale SIGUSR1 pthread_sigmask(SIG_UNBLOCK,&block_sig,NULL); while (1) { // selezione un intervallo casuale di tempo i=rand()%9+1; // avvisa printf("Thread %ld: going to sleep for %d sec...\n",who_i_am,i); // e dormi sleep(i); // prova ad acquisire lo spinlock if (pthread_spin_trylock(&spinlock)) { // in caso contrario avvisa printf("Thread %ld: wait for the spinlock...\n",who_i_am); // e attendi pthread_spin_lock(&spinlock); } // da qui ho acquisito lo spinlock // seleziona un intervallo casuale di tempo i=rand()%9+1; // avvisa printf("Thread %ld: spinlock obtained and now wait for %d sec...\n",who_i_am,i); // e dormi sleep(i); printf("Thread %ld: unlock spinlock...\n",who_i_am); // rilascia lo spinlock pthread_spin_unlock(&spinlock); } return NULL; }
static void* fn_chld(void *arg) { struct sigaction act; thread_state = ENTERED_THREAD; rc = 0; /* Set up child thread to handle SIGALRM */ act.sa_flags = 0; act.sa_handler = sig_handler; sigfillset(&act.sa_mask); sigaction(SIGALRM, &act, 0); /* thread: send SIGALRM to me after 2 seconds in case in spins on trylock */ alarm(2); printf("thread: attempt trylock\n"); rc = pthread_spin_trylock(&spinlock); pthread_exit(0); return NULL; }
static int do_test (void) { pthread_spinlock_t s; if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0) { puts ("spin_init failed"); return 1; } if (pthread_spin_lock (&s) != 0) { puts ("1st spin_lock failed"); return 1; } /* Set an alarm for 1 second. The wrapper will expect this. */ alarm (1); #ifdef ORIGINAL_TEST /* ORIGINAL */ /* This call should never return. */ pthread_spin_lock (&s); puts ("2nd spin_lock returned"); #else /* !ORIGINAL */ int r = pthread_spin_lock (&s); if (!r) { puts ("2nd spin_lock succeeded"); } else if (r != EDEADLOCK) { puts ("2nd spin_lock failed but did not EDEADLOCKed"); } // needed to avoid freezing linux pthread_soft_real_time_np(); while (pthread_spin_trylock (&s) == EBUSY) rt_sleep(nano2count(10000)); #endif /* ORIGINAL */ return 1; }
inline bool TryLock() { return pthread_spin_trylock(&m_raw_lock) == 0; }
bool try_lock() { return pthread_spin_trylock(&_psl) == 0; }
int main() { /* Make sure there is process-shared capability. */ #ifndef PTHREAD_PROCESS_SHARED fprintf(stderr,"process-shared attribute is not available for testing\n"); return PTS_UNSUPPORTED; #endif int pshared = PTHREAD_PROCESS_SHARED; char shm_name[] = "tmp_pthread_spinlock_getpshared"; int shm_fd; int pid; /* Create shared object */ shm_unlink(shm_name); shm_fd = shm_open(shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); if(shm_fd == -1) { perror("Error at shm_open()"); return PTS_UNRESOLVED; } if(ftruncate(shm_fd, sizeof(struct shmstruct)) != 0) { perror("Error at ftruncate()"); shm_unlink(shm_name); return PTS_UNRESOLVED; } /* Map the shared memory object to parent's memory */ spinlock_data = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0); if(spinlock_data == MAP_FAILED) { perror("Error at first mmap()"); shm_unlink(shm_name); return PTS_UNRESOLVED; } /* Initialize spinlock */ if((pthread_spin_init(&(spinlock_data->spinlock), pshared)) != 0) { printf("Test FAILED: Error at pthread_rwlock_init()\n"); return PTS_FAIL; } printf("main: attempt spin lock\n"); if((pthread_spin_lock(&(spinlock_data->spinlock))) != 0) { printf("Error at pthread_spin_lock()\n"); return PTS_UNRESOLVED; } printf("main: acquired spin lock\n"); /* Initialize spinlock data */ spinlock_data->data = 0; /* Fork a child process */ pid = fork(); if(pid == -1) { perror("Error at fork()"); return PTS_UNRESOLVED; } else if(pid > 0) { /* Parent */ /* wait until child writes to spinlock data */ while(spinlock_data->data != 1) sleep(1); printf("main: unlock spin lock\n"); if(pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) { printf("Parent: error at pthread_spin_unlock()\n"); return PTS_UNRESOLVED; } /* Tell child that parent unlocked the spin lock */ spinlock_data->data = 2; /* Wait until child ends */ wait(NULL); if((shm_unlink(shm_name)) != 0) { perror("Error at shm_unlink()"); return PTS_UNRESOLVED; } printf("Test PASSED\n"); return PTS_PASS; } else { /* Child */ /* Map the shared object to child's memory */ spinlock_data = mmap(NULL, sizeof(struct shmstruct), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0); if(spinlock_data == MAP_FAILED) { perror("child : Error at mmap()"); return PTS_UNRESOLVED; } printf("child: attempt spin lock\n"); if((pthread_spin_trylock(&(spinlock_data->spinlock))) != EBUSY) { printf("Test FAILED: Child expects EBUSY\n"); return PTS_FAIL; } printf("child: correctly got EBUSY\n"); /* Tell parent it can unlock now */ spinlock_data->data = 1; /* Wait for parent to unlock spinlock */ while(spinlock_data->data != 2) sleep(1); /* Child tries to get spin lock after parent unlock, * it should get the lock. */ printf("child: attempt spin lock\n"); if((pthread_spin_trylock(&(spinlock_data->spinlock))) != 0) { printf("Test FAILED: Child should get the lock\n"); return PTS_FAIL; } printf("child: acquired spin lock\n"); printf("child: unlock spin lock\n"); if(pthread_spin_unlock(&(spinlock_data->spinlock)) != 0) { printf("Child: error at pthread_spin_unlock()\n"); return PTS_UNRESOLVED; } if(pthread_spin_destroy(&(spinlock_data->spinlock)) != 0) { printf("Child: error at pthread_spin_destroy()\n"); return PTS_UNRESOLVED; } } }
int trylock() { return pthread_spin_trylock(&locker); }
static int swSpinLock_trylock(swLock *lock) { return pthread_spin_trylock(&lock->object.spinlock.lock_t); }
int main(int argc, char ** argv){ pthread_spinlock_t * sl1; int rv,fd; int * count; short rv_short; int i,x=0; void * map_region; char * file; if (argc!=2){ fprintf(stderr, "USAGE: guestlock <file>\n"); exit(-1); } file=strdup(argv[1]); printf("[GUESTLOCK] locking on file %s\n", file); if ((fd=open(file, O_RDWR)) < 0){ fprintf(stderr, "ERROR: cannot open file\n"); exit(-1); } if ((map_region=mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0))<0){ fprintf(stderr, "ERROR: cannot mmap file\n"); } else { printf("[GRABLOCK] mapped to %p\n", map_region); } sl1=map_region; count=map_region + sizeof(pthread_spinlock_t); printf("[GRABLOCK] init locking (0x%x)\n", sl1); // pthread_spin_init(sl1, PTHREAD_PROCESS_SHARED); /* this would lock the lock */ rv=pthread_spin_trylock(sl1); printf("rv=%d\n",rv); sleep(1); /* close the file and unmap the region */ pthread_spin_destroy(sl1); munmap(map_region,1024); close(fd); printf("[GRABLOCK] exiting\n"); /* rv=pthread_spin_trylock(sl1); printf("retval is %d\n", rv); rv=pthread_spin_lock(sl1); printf("retval is %d\n", rv); */ /* rv=pthread_spin_lock(sl1); printf("retval is %d\n", rv); rv=pthread_spin_lock(sl1); printf("retval is %d\n", rv); */ }
int main( int argc, char **argv ) #endif { pthread_spinlock_t spinlock; int status; rtems_status_code rstatus; rtems_id taskid; puts( "\n\n*** POSIX SPINLOCK TEST 01 ***" ); puts( "pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ) -- EINVAL" ); status = pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_init( NULL, PTHREAD_PROCESS_SHARED ) -- EINVAL" ); status = pthread_spin_init( NULL, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_init( &spinlock, 0x1234 ) -- EINVAL" ); status = pthread_spin_init( &spinlock, 0x1234 ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ) -- EINVAL" ); status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_SHARED ); rtems_test_assert( status == EINVAL ); /* This successfully creates one */ puts( "pthread_spin_init( &Spinlock, PTHREAD_PROCESS_PRIVATE ) -- OK" ); status = pthread_spin_init( &Spinlock, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == 0 ); puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- EAGAIN" ); status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EAGAIN ); puts( "pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ) -- EAGAIN" ); status = pthread_spin_init( &spinlock, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EAGAIN ); puts( "pthread_spin_lock( NULL ) -- EINVAL" ); status = pthread_spin_lock( NULL ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_trylock( NULL ) -- EINVAL" ); status = pthread_spin_trylock( NULL ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_unlock( NULL ) -- EINVAL" ); status = pthread_spin_unlock( NULL ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_destroy( NULL ) -- EINVAL" ); status = pthread_spin_destroy( NULL ); rtems_test_assert( status == EINVAL ); spinlock = 0; puts( "pthread_spin_lock( &spinlock ) -- EINVAL" ); status = pthread_spin_lock( &spinlock ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_trylock( &spinlock ) -- EINVAL" ); status = pthread_spin_trylock( &spinlock ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_unlock( &spinlock ) -- EINVAL" ); status = pthread_spin_unlock( &spinlock ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_destroy( &spinlock ) -- EINVAL" ); status = pthread_spin_destroy( &spinlock ); rtems_test_assert( status == EINVAL ); puts( "pthread_spin_unlock( &Spinlock ) -- already unlocked OK" ); status = pthread_spin_unlock( &Spinlock ); rtems_test_assert( status == 0 ); /* Now some basic locking and unlocking with a deadlock verification */ puts( "pthread_spin_lock( &Spinlock ) -- OK" ); status = pthread_spin_lock( &Spinlock ); rtems_test_assert( status == 0 ); puts( "pthread_spin_lock( &Spinlock ) -- EDEADLK" ); status = pthread_spin_lock( &Spinlock ); rtems_test_assert( status == EDEADLK ); puts( "pthread_spin_trylock( &Spinlock ) -- EDEADLK" ); status = pthread_spin_trylock( &Spinlock ); rtems_test_assert( status == EDEADLK ); puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); status = pthread_spin_unlock( &Spinlock ); rtems_test_assert( status == 0 ); /* Try lock/unlock pair */ puts( "pthread_spin_trylock( &Spinlock ) -- OK" ); status = pthread_spin_trylock( &Spinlock ); rtems_test_assert( status == 0 ); puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); status = pthread_spin_unlock( &Spinlock ); rtems_test_assert( status == 0 ); /* Let another thread lock a spinlock and we contend with it */ mainThreadSpinning = 0; /* Create a helper task */ rstatus = rtems_task_create( rtems_build_name( 'S', 'P', 'I', 'N' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &taskid ); rtems_test_assert( rstatus == RTEMS_SUCCESSFUL ); rstatus = rtems_task_start( taskid, SpinlockThread, 0 ); rtems_test_assert( rstatus == RTEMS_SUCCESSFUL ); /* We should be preempted immediately. The thread is expected to: * + verify we haven't set the main thread spinning flag * + lock the spinlock * + delay */ mainThreadSpinning = 1; puts( "pthread_spin_lock( &Spinlock ) -- OK" ); status = pthread_spin_lock( &Spinlock ); rtems_test_assert( status == 0 ); /* The thread wakes up, unlocks spin lock, and deletes itself. * So when we get back here, about a second has passed and we now * have the spinlock locked. */ /* spin lock should be locked when we return so destroying it gives busy */ puts( "pthread_spin_destroy( &Spinlock ) -- EBUSY" ); status = pthread_spin_destroy( &Spinlock ); rtems_test_assert( status == EBUSY ); /* Unlock it for a normal destroy */ puts( "pthread_spin_unlock( &Spinlock ) -- OK" ); status = pthread_spin_unlock( &Spinlock ); rtems_test_assert( status == 0 ); puts( "pthread_spin_destroy( &Spinlock ) -- OK" ); status = pthread_spin_destroy( &Spinlock ); rtems_test_assert( status == 0 ); /*************** END OF TEST *****************/ puts( "*** END OF POSIX SPINLOCK TEST 01 ***" ); exit(0); }
int mutex_enter (dk_mutex_t *mtx) #endif { #ifdef MTX_DEBUG du_thread_t * self = thread_current (); #endif int rc; #ifdef MTX_DEBUG assert (mtx->mtx_owner != self || !self); if (mtx->mtx_entry_check && !mtx->mtx_entry_check (mtx, self, mtx->mtx_entry_check_cd)) GPF_T1 ("Mtx entry check fail"); #endif #ifdef MTX_METER #if HAVE_SPINLOCK if (MUTEX_TYPE_SPIN == mtx->mtx_type) rc = pthread_spin_trylock (&mtx->l.spinl); else #endif rc = pthread_mutex_trylock ((pthread_mutex_t*) &mtx->mtx_mtx); if (TRYLOCK_SUCCESS != rc) { long long wait_ts = rdtsc (); static int unnamed_waits; #if HAVE_SPINLOCK if (MUTEX_TYPE_SPIN == mtx->mtx_type) rc = pthread_spin_lock (&mtx->l.spinl); else #endif rc = pthread_mutex_lock ((pthread_mutex_t*) &mtx->mtx_mtx); mtx->mtx_wait_clocks += rdtsc () - wait_ts; mtx->mtx_waits++; if (!mtx->mtx_name) unnamed_waits++; /*for dbg breakpoint */ mtx->mtx_enters++; } else mtx->mtx_enters++; #else #if HAVE_SPINLOCK if (MUTEX_TYPE_SPIN == mtx->mtx_type) rc = pthread_spin_lock (&mtx->l.spinl); else #endif rc = pthread_mutex_lock ((pthread_mutex_t*) &mtx->mtx_mtx); #endif CKRET (rc); #ifdef MTX_DEBUG assert (mtx->mtx_owner == NULL); mtx->mtx_owner = self; mtx->mtx_entry_file = (char *) file; mtx->mtx_entry_line = line; #endif return 0; failed: GPF_T1 ("mutex_enter() failed"); return -1; }
/* The fault handler function. * * OK. The rules of the battle are those: * * 1. Can't use any function that relies on malloc and friends working as the malloc arena may be corrupt. * 2. Can only use a the POSIX.1-2003 list of async-safe functions. * 3. Some of the functions on the list are not always safe (like fork when atfork() is used), * so need to avoid these also. * 4. No locking allowed. We don't know in what state the process/thread was when the exception * occured. */ void fault_handler (int signal, siginfo_t * siginfo, void *context) { int i, ret; #ifdef USE_THREADS ret=pthread_spin_trylock(&g_thread_lock); if (EBUSY==ret) { /* Think of the following as an async-signal safe super sched_yield that * yields even to threads with lower real-time priority */ sigset_t smask; sigemptyset(&smask); pselect(0, NULL, NULL, NULL, NULL, &smask); } #endif /* USE_THREADS */ /* Get the backtrace. See signal_backtrace for the parameters */ g_crash_msg.num_backtrace_frames=signal_backtrace(g_crash_msg.backtrace, CRASH_MAX_BACKTRACE_DEPTH, context, 0); /* Grab the kernel thread id. Because signal handler are shared between all * threads of the same process, this can only be doen in fault time. */ g_crash_msg.thread_id=gettid(); /* Grab the signal number */ g_crash_msg.signal_number=signal; /* Grab time stamp */ clock_gettime(CLOCK_REALTIME, &g_crash_msg.timestamp); /* Copy the assert buffer without using strings.h fucntions. */ for(i=0; i< CRASH_ASSERT_BUFFER_SIZE; ++i) { g_crash_msg.assert_buffer[i]=*(g_assert_buf_ptr++); } if (siginfo) /* No reasons for this to be NULL, but still... */ { /* See description of these in crash_msg.h */ g_crash_msg.signal_code=siginfo->si_code; g_crash_msg.fault_address=siginfo->si_addr; g_crash_msg.signal_errno=siginfo->si_errno; g_crash_msg.handler_errno=errno; } retry_write: ret=write(g_logfd, &g_crash_msg, sizeof(g_crash_msg)); /* If we got interrupt by a signal, retry the write. * This shouldn't really happen since we mask all signals * during the handler run via sigaction sa_mask field but * it can't hurt to test. * * It's useless to test for any other condition since we * can't do anything if we fail */ if(ret && EINTR==errno) goto retry_write; /* We use backtrace_symbols_fd rather then backtrace_symbols since * the latter uses malloc to allocate memory and if we got here * because of malloc arena curroption we'll double fault. */ backtrace_symbols_fd(g_crash_msg.backtrace, g_crash_msg.num_backtrace_frames, g_logfd); close(g_logfd); /* Produce a core dump for post morteum debugging */ abort(); assert(0 /* Not Reached */); return; }
static int do_test (void) { size_t ps = sysconf (_SC_PAGESIZE); char tmpfname[] = "/tmp/tst-spin2.XXXXXX"; char data[ps]; void *mem; int fd; pthread_spinlock_t *s; pid_t pid; char *p; int err; fd = mkstemp (tmpfname); if (fd == -1) { printf ("cannot open temporary file: %m\n"); return 1; } /* Make sure it is always removed. */ unlink (tmpfname); /* Create one page of data. */ memset (data, '\0', ps); /* Write the data to the file. */ if (write (fd, data, ps) != (ssize_t) ps) { puts ("short write"); return 1; } mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mem == MAP_FAILED) { printf ("mmap failed: %m\n"); return 1; } s = (pthread_spinlock_t *) (((uintptr_t) mem + __alignof (pthread_spinlock_t)) & ~(__alignof (pthread_spinlock_t) - 1)); p = (char *) (s + 1); if (pthread_spin_init (s, PTHREAD_PROCESS_SHARED) != 0) { puts ("spin_init failed"); return 1; } if (pthread_spin_lock (s) != 0) { puts ("spin_lock failed"); return 1; } err = pthread_spin_trylock (s); if (err == 0) { puts ("1st spin_trylock succeeded"); return 1; } else if (err != EBUSY) { puts ("1st spin_trylock didn't return EBUSY"); return 1; } err = pthread_spin_unlock (s); if (err != 0) { puts ("parent: spin_unlock failed"); return 1; } err = pthread_spin_trylock (s); if (err != 0) { puts ("2nd spin_trylock failed"); return 1; } *p = 0; puts ("going to fork now"); pid = fork (); if (pid == -1) { puts ("fork failed"); return 1; } else if (pid == 0) { /* Play some lock ping-pong. It's our turn to unlock first. */ if ((*p)++ != 0) { puts ("child: *p != 0"); return 1; } if (pthread_spin_unlock (s) != 0) { puts ("child: 1st spin_unlock failed"); return 1; } puts ("child done"); } else { if (pthread_spin_lock (s) != 0) { puts ("parent: 2nd spin_lock failed"); return 1; } puts ("waiting for child"); waitpid (pid, NULL, 0); puts ("parent done"); } return 0; }