[BACK]Return to linux_futex.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / linux / common

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/compat/linux/common/Attic/linux_futex.c between version 1.33 and 1.34

version 1.33, 2014/02/11 16:00:13 version 1.34, 2016/05/20 13:54:34
Line 58  __KERNEL_RCSID(1, "$NetBSD$");
Line 58  __KERNEL_RCSID(1, "$NetBSD$");
 struct futex;  struct futex;
   
 struct waiting_proc {  struct waiting_proc {
         lwp_t *wp_l;          struct futex *wp_futex;
         struct futex *wp_new_futex;  
         kcondvar_t wp_futex_cv;          kcondvar_t wp_futex_cv;
         TAILQ_ENTRY(waiting_proc) wp_list;          TAILQ_ENTRY(waiting_proc) wp_list;
         TAILQ_ENTRY(waiting_proc) wp_rqlist;          bool wp_onlist;
 };  };
 struct futex {  struct futex {
         void *f_uaddr;          void *f_uaddr;
Line 70  struct futex {
Line 69  struct futex {
         uint32_t f_bitset;          uint32_t f_bitset;
         LIST_ENTRY(futex) f_list;          LIST_ENTRY(futex) f_list;
         TAILQ_HEAD(, waiting_proc) f_waiting_proc;          TAILQ_HEAD(, waiting_proc) f_waiting_proc;
         TAILQ_HEAD(, waiting_proc) f_requeue_proc;  
 };  };
   
 static LIST_HEAD(futex_list, futex) futex_list;  static LIST_HEAD(futex_list, futex) futex_list;
Line 432  futex_get(void *uaddr, uint32_t bitset)
Line 430  futex_get(void *uaddr, uint32_t bitset)
         f->f_bitset = bitset;          f->f_bitset = bitset;
         f->f_refcount = 1;          f->f_refcount = 1;
         TAILQ_INIT(&f->f_waiting_proc);          TAILQ_INIT(&f->f_waiting_proc);
         TAILQ_INIT(&f->f_requeue_proc);  
         LIST_INSERT_HEAD(&futex_list, f, f_list);          LIST_INSERT_HEAD(&futex_list, f, f_list);
   
         return f;          return f;
Line 456  futex_put(struct futex *f)
Line 453  futex_put(struct futex *f)
         f->f_refcount--;          f->f_refcount--;
         if (f->f_refcount == 0) {          if (f->f_refcount == 0) {
                 KASSERT(TAILQ_EMPTY(&f->f_waiting_proc));                  KASSERT(TAILQ_EMPTY(&f->f_waiting_proc));
                 KASSERT(TAILQ_EMPTY(&f->f_requeue_proc));  
                 LIST_REMOVE(f, f_list);                  LIST_REMOVE(f, f_list);
                 kmem_free(f, sizeof(*f));                  kmem_free(f, sizeof(*f));
         }          }
Line 465  futex_put(struct futex *f)
Line 461  futex_put(struct futex *f)
 static int  static int
 futex_sleep(struct futex **fp, lwp_t *l, int timeout, struct waiting_proc *wp)  futex_sleep(struct futex **fp, lwp_t *l, int timeout, struct waiting_proc *wp)
 {  {
         struct futex *f, *newf;          struct futex *f;
         int ret;          int ret;
   
         FUTEX_LOCKASSERT;          FUTEX_LOCKASSERT;
   
         f = *fp;          f = *fp;
         wp->wp_l = l;          wp->wp_futex = f;
         wp->wp_new_futex = NULL;  
   
 requeue:  
         TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list);          TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list);
           wp->wp_onlist = true;
         ret = cv_timedwait_sig(&wp->wp_futex_cv, &futex_lock, timeout);          ret = cv_timedwait_sig(&wp->wp_futex_cv, &futex_lock, timeout);
         TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);  
   
         /* if futex_wake() tells us to requeue ... */          /*
         newf = wp->wp_new_futex;           * we may have been requeued to a different futex before we were
         if (ret == 0 && newf != NULL) {           * woken up, so let the caller know which futex to put.   if we were
                 /* ... requeue ourselves on the new futex */           * woken by futex_wake() then it took us off the waiting list,
                 futex_put(f);           * but if our sleep was interrupted or timed out then we might
                 wp->wp_new_futex = NULL;           * need to take ourselves off the waiting list.
                 TAILQ_REMOVE(&newf->f_requeue_proc, wp, wp_rqlist);           */
                 *fp = f = newf;  
                 goto requeue;          f = wp->wp_futex;
           if (wp->wp_onlist) {
                   TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
         }          }
           *fp = f;
         return ret;          return ret;
 }  }
   
 static int  static int
 futex_wake(struct futex *f, int n, struct futex *newf, int n2)  futex_wake(struct futex *f, int n, struct futex *newf, int n2)
 {  {
         struct waiting_proc *wp, *wpnext;          struct waiting_proc *wp;
         int count;          int count = 0;
   
         FUTEX_LOCKASSERT;          FUTEX_LOCKASSERT;
   
         count = newf ? 0 : 1;  
   
         /*          /*
          * first, wake up any threads sleeping on this futex.           * wake up up to n threads waiting on this futex.
          * note that sleeping threads are not in the process of requeueing.  
          */           */
   
         TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) {          while (n--) {
                 KASSERT(wp->wp_new_futex == NULL);                  wp = TAILQ_FIRST(&f->f_waiting_proc);
                   if (wp == NULL)
                 FUTEXPRINTF(("%s: signal f %p l %p ref %d\n", __func__,                          return count;
                     f, wp->wp_l, f->f_refcount));  
                   KASSERT(f == wp->wp_futex);
                   TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
                   wp->wp_onlist = false;
                 cv_signal(&wp->wp_futex_cv);                  cv_signal(&wp->wp_futex_cv);
                 if (count <= n) {                  count++;
                         count++;  
                 } else {  
                         if (newf == NULL)  
                                 break;  
   
                         /* matching futex_put() is called by the other thread. */  
                         futex_ref(newf);  
                         wp->wp_new_futex = newf;  
                         TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist);  
                         FUTEXPRINTF(("%s: requeue newf %p l %p ref %d\n",  
                             __func__, newf, wp->wp_l, newf->f_refcount));  
                         if (count - n >= n2)  
                                 goto out;  
                 }  
         }          }
           if (newf == NULL)
                   return count;
   
         /*          /*
          * next, deal with threads that are requeuing to this futex.           * then requeue up to n2 additional threads to newf
          * we don't need to signal these threads, any thread on the           * (without waking them up).
          * requeue list has already been signaled but hasn't had a chance  
          * to run and requeue itself yet.  if we would normally wake  
          * a thread, just remove the requeue info.  if we would normally  
          * requeue a thread, change the requeue target.  
          */           */
   
         TAILQ_FOREACH_SAFE(wp, &f->f_requeue_proc, wp_rqlist, wpnext) {          while (n2--) {
                 KASSERT(wp->wp_new_futex == f);                  wp = TAILQ_FIRST(&f->f_waiting_proc);
                   if (wp == NULL)
                           return count;
   
                 FUTEXPRINTF(("%s: unrequeue f %p l %p ref %d\n", __func__,                  KASSERT(f == wp->wp_futex);
                     f, wp->wp_l, f->f_refcount));                  TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
                 wp->wp_new_futex = NULL;  
                 TAILQ_REMOVE(&f->f_requeue_proc, wp, wp_rqlist);  
                 futex_put(f);                  futex_put(f);
   
                 if (count <= n) {                  wp->wp_futex = newf;
                         count++;                  futex_ref(newf);
                 } else {                  TAILQ_INSERT_TAIL(&newf->f_waiting_proc, wp, wp_list);
                         if (newf == NULL)                  count++;
                                 break;  
   
                         /* matching futex_put() is called by the other thread. */  
                         futex_ref(newf);  
                         wp->wp_new_futex = newf;  
                         TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist);  
                         FUTEXPRINTF(("%s: rerequeue newf %p l %p ref %d\n",  
                             __func__, newf, wp->wp_l, newf->f_refcount));  
                         if (count - n >= n2)  
                                 break;  
                 }  
         }          }
   
 out:  
         return count;          return count;
 }  }
   

Legend:
Removed from v.1.33  
changed lines
  Added in v.1.34

CVSweb <webmaster@jp.NetBSD.org>