7

I didn't find it in Mac, but almost all Linux os support it.. Any one knows how to port it to mac?

JustQieTry
  • 491
  • 1
  • 6
  • 13

4 Answers4

11

Here is drop in replacement code. You should be able to put this in a header file and drop it in your project.

typedef int pthread_spinlock_t;

int pthread_spin_init(pthread_spinlock_t *lock, int pshared) {
    __asm__ __volatile__ ("" ::: "memory");
    *lock = 0;
    return 0;
}

int pthread_spin_destroy(pthread_spinlock_t *lock) {
    return 0;
}

int pthread_spin_lock(pthread_spinlock_t *lock) {
    while (1) {
        int i;
        for (i=0; i < 10000; i++) {
            if (__sync_bool_compare_and_swap(lock, 0, 1)) {
                return 0;
            }
        }
        sched_yield();
    }
}

int pthread_spin_trylock(pthread_spinlock_t *lock) {
    if (__sync_bool_compare_and_swap(lock, 0, 1)) {
        return 0;
    }
    return EBUSY;
}

int pthread_spin_unlock(pthread_spinlock_t *lock) {
    __asm__ __volatile__ ("" ::: "memory");
    *lock = 0;
    return 0;
}

See discussion, and Github source

EDIT: Here's a class that works on all OSes that includes a workaround for missing pthread spinlocks on OSX:

class Spinlock
{
private:    //private copy-ctor and assignment operator ensure the lock never gets copied, which might cause issues.
    Spinlock operator=(const Spinlock & asdf);
    Spinlock(const Spinlock & asdf);
#ifdef __APPLE__
    OSSpinLock m_lock;
public:
    Spinlock()
    : m_lock(0)
    {}
    void lock() {
        OSSpinLockLock(&m_lock);
    }
    bool try_lock() {
        return OSSpinLockTry(&m_lock);
    }
    void unlock() {
        OSSpinLockUnlock(&m_lock);
    }
#else
    pthread_spinlock_t m_lock;
public:
    Spinlock() {
        pthread_spin_init(&m_lock, 0);
    }

    void lock() {
        pthread_spin_lock(&m_lock);
    }
    bool try_lock() {
        int ret = pthread_spin_trylock(&m_lock);
        return ret != 16;   //EBUSY == 16, lock is already taken
    }
    void unlock() {
        pthread_spin_unlock(&m_lock);
    }
    ~Spinlock() {
        pthread_spin_destroy(&m_lock);
    }
#endif
};
leecbaker
  • 3,611
  • 2
  • 35
  • 51
8

Try using OSSpinLock instead. Documentation is here: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/spinlock.3.html

Catfish_Man
  • 41,261
  • 11
  • 67
  • 84
  • Honestly at this point the newer os_unfair_lock is a better choice anyway. See https://developer.apple.com/documentation/os/1646466-os_unfair_lock_lock?language=objc etc... – Catfish_Man Aug 06 '17 at 09:54
3

If the performance of your lock is not critical, pthread_mutex_t can be used as a drop replacement for pthread_spinlock_t, which makes porting easy.

Garrett Hyde
  • 5,409
  • 8
  • 49
  • 55
1

I have used instead (that is natively supported by OS X intel)

  1. pthread_rwlock_t lock;
  2. pthread_rwlock_init
  3. pthread_rwlock_wrlock
  4. pthread_rwlock_unlock

And that works very fine as well

Danouchka
  • 11
  • 2