Author: kib
Date: Mon Mar 21 06:40:54 2016
New Revision: 297138
URL: https://svnweb.freebsd.org/changeset/base/297138

Log:
  Implement process-shared spinlocks.
  
  Sponsored by: The FreeBSD Foundation

Modified:
  head/lib/libthr/thread/thr_pspinlock.c

Modified: head/lib/libthr/thread/thr_pspinlock.c
==============================================================================
--- head/lib/libthr/thread/thr_pspinlock.c      Mon Mar 21 05:59:05 2016        
(r297137)
+++ head/lib/libthr/thread/thr_pspinlock.c      Mon Mar 21 06:40:54 2016        
(r297138)
@@ -1,7 +1,11 @@
 /*-
  * Copyright (c) 2003 David Xu <davi...@freebsd.org>
+ * Copyright (c) 2016 The FreeBSD Foundation
  * All rights reserved.
  *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -46,93 +50,100 @@ int
 _pthread_spin_init(pthread_spinlock_t *lock, int pshared)
 {
        struct pthread_spinlock *lck;
-       int ret;
 
-       if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE)
-               ret = EINVAL;
-       else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL)
-               ret = ENOMEM;
-       else {
-               _thr_umutex_init(&lck->s_lock);
+       if (lock == NULL)
+               return (EINVAL);
+       if (pshared == PTHREAD_PROCESS_PRIVATE) {
+               lck = malloc(sizeof(struct pthread_spinlock));
+               if (lck == NULL)
+                       return (ENOMEM);
                *lock = lck;
-               ret = 0;
+       } else if (pshared == PTHREAD_PROCESS_SHARED) {
+               lck = __thr_pshared_offpage(lock, 1);
+               if (lck == NULL)
+                       return (EFAULT);
+               *lock = THR_PSHARED_PTR;
+       } else {
+               return (EINVAL);
        }
-
-       return (ret);
+       _thr_umutex_init(&lck->s_lock);
+       return (0);
 }
 
 int
 _pthread_spin_destroy(pthread_spinlock_t *lock)
 {
+       void *l;
        int ret;
 
-       if (lock == NULL || *lock == NULL)
+       if (lock == NULL || *lock == NULL) {
                ret = EINVAL;
-       else {
+       } else if (*lock == THR_PSHARED_PTR) {
+               l = __thr_pshared_offpage(lock, 0);
+               if (l != NULL)
+                       __thr_pshared_destroy(l);
+               ret = 0;
+       } else {
                free(*lock);
                *lock = NULL;
                ret = 0;
        }
-
        return (ret);
 }
 
 int
 _pthread_spin_trylock(pthread_spinlock_t *lock)
 {
-       struct pthread *curthread = _get_curthread();
        struct pthread_spinlock *lck;
-       int ret;
 
-       if (lock == NULL || (lck = *lock) == NULL)
-               ret = EINVAL;
-       else
-               ret = THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock);
-       return (ret);
+       if (lock == NULL || *lock == NULL)
+               return (EINVAL);
+       lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+       if (lck == NULL)
+               return (EINVAL);
+       return (THR_UMUTEX_TRYLOCK(_get_curthread(), &lck->s_lock));
 }
 
 int
 _pthread_spin_lock(pthread_spinlock_t *lock)
 {
-       struct pthread *curthread = _get_curthread();
+       struct pthread *curthread;
        struct pthread_spinlock *lck;
-       int ret, count;
+       int count;
 
-       if (lock == NULL || (lck = *lock) == NULL)
-               ret = EINVAL;
-       else {
-               count = SPIN_COUNT;
-               while ((ret = THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock)) != 
0) {
-                       while (lck->s_lock.m_owner) {
-                               if (!_thr_is_smp) {
+       if (lock == NULL)
+               return (EINVAL);
+       lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+       if (lck == NULL)
+               return (EINVAL);
+
+       curthread = _get_curthread();
+       count = SPIN_COUNT;
+       while (THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock) != 0) {
+               while (lck->s_lock.m_owner) {
+                       if (!_thr_is_smp) {
+                               _pthread_yield();
+                       } else {
+                               CPU_SPINWAIT;
+                               if (--count <= 0) {
+                                       count = SPIN_COUNT;
                                        _pthread_yield();
-                               } else {
-                                       CPU_SPINWAIT;
-
-                                       if (--count <= 0) {
-                                               count = SPIN_COUNT;
-                                               _pthread_yield();
-                                       }
                                }
                        }
                }
-               ret = 0;
        }
-
-       return (ret);
+       return (0);
 }
 
 int
 _pthread_spin_unlock(pthread_spinlock_t *lock)
 {
-       struct pthread *curthread = _get_curthread();
        struct pthread_spinlock *lck;
-       int ret;
 
-       if (lock == NULL || (lck = *lock) == NULL)
-               ret = EINVAL;
-       else {
-               ret = THR_UMUTEX_UNLOCK(curthread, &lck->s_lock);
-       }
-       return (ret);
+       if (lock == NULL)
+               return (EINVAL);
+       lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+       if (lck == NULL)
+               return (EINVAL);
+       return (THR_UMUTEX_UNLOCK(_get_curthread(), &lck->s_lock));
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to