Home | History | Annotate | Line # | Download | only in libgomp
iter_ull.c revision 1.1.1.1.4.2
      1  1.1.1.1.4.2  yamt /* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
      2  1.1.1.1.4.2  yamt    Contributed by Richard Henderson <rth (at) redhat.com>.
      3  1.1.1.1.4.2  yamt 
      4  1.1.1.1.4.2  yamt    This file is part of the GNU OpenMP Library (libgomp).
      5  1.1.1.1.4.2  yamt 
      6  1.1.1.1.4.2  yamt    Libgomp is free software; you can redistribute it and/or modify it
      7  1.1.1.1.4.2  yamt    under the terms of the GNU General Public License as published by
      8  1.1.1.1.4.2  yamt    the Free Software Foundation; either version 3, or (at your option)
      9  1.1.1.1.4.2  yamt    any later version.
     10  1.1.1.1.4.2  yamt 
     11  1.1.1.1.4.2  yamt    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1.1.1.4.2  yamt    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     13  1.1.1.1.4.2  yamt    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     14  1.1.1.1.4.2  yamt    more details.
     15  1.1.1.1.4.2  yamt 
     16  1.1.1.1.4.2  yamt    Under Section 7 of GPL version 3, you are granted additional
     17  1.1.1.1.4.2  yamt    permissions described in the GCC Runtime Library Exception, version
     18  1.1.1.1.4.2  yamt    3.1, as published by the Free Software Foundation.
     19  1.1.1.1.4.2  yamt 
     20  1.1.1.1.4.2  yamt    You should have received a copy of the GNU General Public License and
     21  1.1.1.1.4.2  yamt    a copy of the GCC Runtime Library Exception along with this program;
     22  1.1.1.1.4.2  yamt    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23  1.1.1.1.4.2  yamt    <http://www.gnu.org/licenses/>.  */
     24  1.1.1.1.4.2  yamt 
     25  1.1.1.1.4.2  yamt /* This file contains routines for managing work-share iteration, both
     26  1.1.1.1.4.2  yamt    for loops and sections.  */
     27  1.1.1.1.4.2  yamt 
     28  1.1.1.1.4.2  yamt #include "libgomp.h"
     29  1.1.1.1.4.2  yamt #include <stdlib.h>
     30  1.1.1.1.4.2  yamt 
     31  1.1.1.1.4.2  yamt typedef unsigned long long gomp_ull;
     32  1.1.1.1.4.2  yamt 
     33  1.1.1.1.4.2  yamt /* This function implements the STATIC scheduling method.  The caller should
     34  1.1.1.1.4.2  yamt    iterate *pstart <= x < *pend.  Return zero if there are more iterations
     35  1.1.1.1.4.2  yamt    to perform; nonzero if not.  Return less than 0 if this thread had
     36  1.1.1.1.4.2  yamt    received the absolutely last iteration.  */
     37  1.1.1.1.4.2  yamt 
     38  1.1.1.1.4.2  yamt int
     39  1.1.1.1.4.2  yamt gomp_iter_ull_static_next (gomp_ull *pstart, gomp_ull *pend)
     40  1.1.1.1.4.2  yamt {
     41  1.1.1.1.4.2  yamt   struct gomp_thread *thr = gomp_thread ();
     42  1.1.1.1.4.2  yamt   struct gomp_team *team = thr->ts.team;
     43  1.1.1.1.4.2  yamt   struct gomp_work_share *ws = thr->ts.work_share;
     44  1.1.1.1.4.2  yamt   unsigned long nthreads = team ? team->nthreads : 1;
     45  1.1.1.1.4.2  yamt 
     46  1.1.1.1.4.2  yamt   if (thr->ts.static_trip == -1)
     47  1.1.1.1.4.2  yamt     return -1;
     48  1.1.1.1.4.2  yamt 
     49  1.1.1.1.4.2  yamt   /* Quick test for degenerate teams and orphaned constructs.  */
     50  1.1.1.1.4.2  yamt   if (nthreads == 1)
     51  1.1.1.1.4.2  yamt     {
     52  1.1.1.1.4.2  yamt       *pstart = ws->next_ull;
     53  1.1.1.1.4.2  yamt       *pend = ws->end_ull;
     54  1.1.1.1.4.2  yamt       thr->ts.static_trip = -1;
     55  1.1.1.1.4.2  yamt       return ws->next_ull == ws->end_ull;
     56  1.1.1.1.4.2  yamt     }
     57  1.1.1.1.4.2  yamt 
     58  1.1.1.1.4.2  yamt   /* We interpret chunk_size zero as "unspecified", which means that we
     59  1.1.1.1.4.2  yamt      should break up the iterations such that each thread makes only one
     60  1.1.1.1.4.2  yamt      trip through the outer loop.  */
     61  1.1.1.1.4.2  yamt   if (ws->chunk_size_ull == 0)
     62  1.1.1.1.4.2  yamt     {
     63  1.1.1.1.4.2  yamt       gomp_ull n, q, i, s0, e0, s, e;
     64  1.1.1.1.4.2  yamt 
     65  1.1.1.1.4.2  yamt       if (thr->ts.static_trip > 0)
     66  1.1.1.1.4.2  yamt 	return 1;
     67  1.1.1.1.4.2  yamt 
     68  1.1.1.1.4.2  yamt       /* Compute the total number of iterations.  */
     69  1.1.1.1.4.2  yamt       if (__builtin_expect (ws->mode, 0) == 0)
     70  1.1.1.1.4.2  yamt 	n = (ws->end_ull - ws->next_ull + ws->incr_ull - 1) / ws->incr_ull;
     71  1.1.1.1.4.2  yamt       else
     72  1.1.1.1.4.2  yamt 	n = (ws->next_ull - ws->end_ull - ws->incr_ull - 1) / -ws->incr_ull;
     73  1.1.1.1.4.2  yamt       i = thr->ts.team_id;
     74  1.1.1.1.4.2  yamt 
     75  1.1.1.1.4.2  yamt       /* Compute the "zero-based" start and end points.  That is, as
     76  1.1.1.1.4.2  yamt 	 if the loop began at zero and incremented by one.  */
     77  1.1.1.1.4.2  yamt       q = n / nthreads;
     78  1.1.1.1.4.2  yamt       q += (q * nthreads != n);
     79  1.1.1.1.4.2  yamt       s0 = q * i;
     80  1.1.1.1.4.2  yamt       e0 = s0 + q;
     81  1.1.1.1.4.2  yamt       if (e0 > n)
     82  1.1.1.1.4.2  yamt 	e0 = n;
     83  1.1.1.1.4.2  yamt 
     84  1.1.1.1.4.2  yamt       /* Notice when no iterations allocated for this thread.  */
     85  1.1.1.1.4.2  yamt       if (s0 >= e0)
     86  1.1.1.1.4.2  yamt 	{
     87  1.1.1.1.4.2  yamt 	  thr->ts.static_trip = 1;
     88  1.1.1.1.4.2  yamt 	  return 1;
     89  1.1.1.1.4.2  yamt 	}
     90  1.1.1.1.4.2  yamt 
     91  1.1.1.1.4.2  yamt       /* Transform these to the actual start and end numbers.  */
     92  1.1.1.1.4.2  yamt       s = s0 * ws->incr_ull + ws->next_ull;
     93  1.1.1.1.4.2  yamt       e = e0 * ws->incr_ull + ws->next_ull;
     94  1.1.1.1.4.2  yamt 
     95  1.1.1.1.4.2  yamt       *pstart = s;
     96  1.1.1.1.4.2  yamt       *pend = e;
     97  1.1.1.1.4.2  yamt       thr->ts.static_trip = (e0 == n ? -1 : 1);
     98  1.1.1.1.4.2  yamt       return 0;
     99  1.1.1.1.4.2  yamt     }
    100  1.1.1.1.4.2  yamt   else
    101  1.1.1.1.4.2  yamt     {
    102  1.1.1.1.4.2  yamt       gomp_ull n, s0, e0, i, c, s, e;
    103  1.1.1.1.4.2  yamt 
    104  1.1.1.1.4.2  yamt       /* Otherwise, each thread gets exactly chunk_size iterations
    105  1.1.1.1.4.2  yamt 	 (if available) each time through the loop.  */
    106  1.1.1.1.4.2  yamt 
    107  1.1.1.1.4.2  yamt       if (__builtin_expect (ws->mode, 0) == 0)
    108  1.1.1.1.4.2  yamt 	n = (ws->end_ull - ws->next_ull + ws->incr_ull - 1) / ws->incr_ull;
    109  1.1.1.1.4.2  yamt       else
    110  1.1.1.1.4.2  yamt 	n = (ws->next_ull - ws->end_ull - ws->incr_ull - 1) / -ws->incr_ull;
    111  1.1.1.1.4.2  yamt       i = thr->ts.team_id;
    112  1.1.1.1.4.2  yamt       c = ws->chunk_size_ull;
    113  1.1.1.1.4.2  yamt 
    114  1.1.1.1.4.2  yamt       /* Initial guess is a C sized chunk positioned nthreads iterations
    115  1.1.1.1.4.2  yamt 	 in, offset by our thread number.  */
    116  1.1.1.1.4.2  yamt       s0 = (thr->ts.static_trip * (gomp_ull) nthreads + i) * c;
    117  1.1.1.1.4.2  yamt       e0 = s0 + c;
    118  1.1.1.1.4.2  yamt 
    119  1.1.1.1.4.2  yamt       /* Detect overflow.  */
    120  1.1.1.1.4.2  yamt       if (s0 >= n)
    121  1.1.1.1.4.2  yamt 	return 1;
    122  1.1.1.1.4.2  yamt       if (e0 > n)
    123  1.1.1.1.4.2  yamt 	e0 = n;
    124  1.1.1.1.4.2  yamt 
    125  1.1.1.1.4.2  yamt       /* Transform these to the actual start and end numbers.  */
    126  1.1.1.1.4.2  yamt       s = s0 * ws->incr_ull + ws->next_ull;
    127  1.1.1.1.4.2  yamt       e = e0 * ws->incr_ull + ws->next_ull;
    128  1.1.1.1.4.2  yamt 
    129  1.1.1.1.4.2  yamt       *pstart = s;
    130  1.1.1.1.4.2  yamt       *pend = e;
    131  1.1.1.1.4.2  yamt 
    132  1.1.1.1.4.2  yamt       if (e0 == n)
    133  1.1.1.1.4.2  yamt 	thr->ts.static_trip = -1;
    134  1.1.1.1.4.2  yamt       else
    135  1.1.1.1.4.2  yamt 	thr->ts.static_trip++;
    136  1.1.1.1.4.2  yamt       return 0;
    137  1.1.1.1.4.2  yamt     }
    138  1.1.1.1.4.2  yamt }
    139  1.1.1.1.4.2  yamt 
    140  1.1.1.1.4.2  yamt 
    141  1.1.1.1.4.2  yamt /* This function implements the DYNAMIC scheduling method.  Arguments are
    142  1.1.1.1.4.2  yamt    as for gomp_iter_ull_static_next.  This function must be called with
    143  1.1.1.1.4.2  yamt    ws->lock held.  */
    144  1.1.1.1.4.2  yamt 
    145  1.1.1.1.4.2  yamt bool
    146  1.1.1.1.4.2  yamt gomp_iter_ull_dynamic_next_locked (gomp_ull *pstart, gomp_ull *pend)
    147  1.1.1.1.4.2  yamt {
    148  1.1.1.1.4.2  yamt   struct gomp_thread *thr = gomp_thread ();
    149  1.1.1.1.4.2  yamt   struct gomp_work_share *ws = thr->ts.work_share;
    150  1.1.1.1.4.2  yamt   gomp_ull start, end, chunk, left;
    151  1.1.1.1.4.2  yamt 
    152  1.1.1.1.4.2  yamt   start = ws->next_ull;
    153  1.1.1.1.4.2  yamt   if (start == ws->end_ull)
    154  1.1.1.1.4.2  yamt     return false;
    155  1.1.1.1.4.2  yamt 
    156  1.1.1.1.4.2  yamt   chunk = ws->chunk_size_ull;
    157  1.1.1.1.4.2  yamt   left = ws->end_ull - start;
    158  1.1.1.1.4.2  yamt   if (__builtin_expect (ws->mode & 2, 0))
    159  1.1.1.1.4.2  yamt     {
    160  1.1.1.1.4.2  yamt       if (chunk < left)
    161  1.1.1.1.4.2  yamt 	chunk = left;
    162  1.1.1.1.4.2  yamt     }
    163  1.1.1.1.4.2  yamt   else
    164  1.1.1.1.4.2  yamt     {
    165  1.1.1.1.4.2  yamt       if (chunk > left)
    166  1.1.1.1.4.2  yamt 	chunk = left;
    167  1.1.1.1.4.2  yamt     }
    168  1.1.1.1.4.2  yamt   end = start + chunk;
    169  1.1.1.1.4.2  yamt 
    170  1.1.1.1.4.2  yamt   ws->next_ull = end;
    171  1.1.1.1.4.2  yamt   *pstart = start;
    172  1.1.1.1.4.2  yamt   *pend = end;
    173  1.1.1.1.4.2  yamt   return true;
    174  1.1.1.1.4.2  yamt }
    175  1.1.1.1.4.2  yamt 
    176  1.1.1.1.4.2  yamt 
    177  1.1.1.1.4.2  yamt #if defined HAVE_SYNC_BUILTINS && defined __LP64__
    178  1.1.1.1.4.2  yamt /* Similar, but doesn't require the lock held, and uses compare-and-swap
    179  1.1.1.1.4.2  yamt    instead.  Note that the only memory value that changes is ws->next_ull.  */
    180  1.1.1.1.4.2  yamt 
    181  1.1.1.1.4.2  yamt bool
    182  1.1.1.1.4.2  yamt gomp_iter_ull_dynamic_next (gomp_ull *pstart, gomp_ull *pend)
    183  1.1.1.1.4.2  yamt {
    184  1.1.1.1.4.2  yamt   struct gomp_thread *thr = gomp_thread ();
    185  1.1.1.1.4.2  yamt   struct gomp_work_share *ws = thr->ts.work_share;
    186  1.1.1.1.4.2  yamt   gomp_ull start, end, nend, chunk;
    187  1.1.1.1.4.2  yamt 
    188  1.1.1.1.4.2  yamt   end = ws->end_ull;
    189  1.1.1.1.4.2  yamt   chunk = ws->chunk_size_ull;
    190  1.1.1.1.4.2  yamt 
    191  1.1.1.1.4.2  yamt   if (__builtin_expect (ws->mode & 1, 1))
    192  1.1.1.1.4.2  yamt     {
    193  1.1.1.1.4.2  yamt       gomp_ull tmp = __sync_fetch_and_add (&ws->next_ull, chunk);
    194  1.1.1.1.4.2  yamt       if (__builtin_expect (ws->mode & 2, 0) == 0)
    195  1.1.1.1.4.2  yamt 	{
    196  1.1.1.1.4.2  yamt 	  if (tmp >= end)
    197  1.1.1.1.4.2  yamt 	    return false;
    198  1.1.1.1.4.2  yamt 	  nend = tmp + chunk;
    199  1.1.1.1.4.2  yamt 	  if (nend > end)
    200  1.1.1.1.4.2  yamt 	    nend = end;
    201  1.1.1.1.4.2  yamt 	  *pstart = tmp;
    202  1.1.1.1.4.2  yamt 	  *pend = nend;
    203  1.1.1.1.4.2  yamt 	  return true;
    204  1.1.1.1.4.2  yamt 	}
    205  1.1.1.1.4.2  yamt       else
    206  1.1.1.1.4.2  yamt 	{
    207  1.1.1.1.4.2  yamt 	  if (tmp <= end)
    208  1.1.1.1.4.2  yamt 	    return false;
    209  1.1.1.1.4.2  yamt 	  nend = tmp + chunk;
    210  1.1.1.1.4.2  yamt 	  if (nend < end)
    211  1.1.1.1.4.2  yamt 	    nend = end;
    212  1.1.1.1.4.2  yamt 	  *pstart = tmp;
    213  1.1.1.1.4.2  yamt 	  *pend = nend;
    214  1.1.1.1.4.2  yamt 	  return true;
    215  1.1.1.1.4.2  yamt 	}
    216  1.1.1.1.4.2  yamt     }
    217  1.1.1.1.4.2  yamt 
    218  1.1.1.1.4.2  yamt   start = ws->next_ull;
    219  1.1.1.1.4.2  yamt   while (1)
    220  1.1.1.1.4.2  yamt     {
    221  1.1.1.1.4.2  yamt       gomp_ull left = end - start;
    222  1.1.1.1.4.2  yamt       gomp_ull tmp;
    223  1.1.1.1.4.2  yamt 
    224  1.1.1.1.4.2  yamt       if (start == end)
    225  1.1.1.1.4.2  yamt 	return false;
    226  1.1.1.1.4.2  yamt 
    227  1.1.1.1.4.2  yamt       if (__builtin_expect (ws->mode & 2, 0))
    228  1.1.1.1.4.2  yamt 	{
    229  1.1.1.1.4.2  yamt 	  if (chunk < left)
    230  1.1.1.1.4.2  yamt 	    chunk = left;
    231  1.1.1.1.4.2  yamt 	}
    232  1.1.1.1.4.2  yamt       else
    233  1.1.1.1.4.2  yamt 	{
    234  1.1.1.1.4.2  yamt 	  if (chunk > left)
    235  1.1.1.1.4.2  yamt 	    chunk = left;
    236  1.1.1.1.4.2  yamt 	}
    237  1.1.1.1.4.2  yamt       nend = start + chunk;
    238  1.1.1.1.4.2  yamt 
    239  1.1.1.1.4.2  yamt       tmp = __sync_val_compare_and_swap (&ws->next_ull, start, nend);
    240  1.1.1.1.4.2  yamt       if (__builtin_expect (tmp == start, 1))
    241  1.1.1.1.4.2  yamt 	break;
    242  1.1.1.1.4.2  yamt 
    243  1.1.1.1.4.2  yamt       start = tmp;
    244  1.1.1.1.4.2  yamt     }
    245  1.1.1.1.4.2  yamt 
    246  1.1.1.1.4.2  yamt   *pstart = start;
    247  1.1.1.1.4.2  yamt   *pend = nend;
    248  1.1.1.1.4.2  yamt   return true;
    249  1.1.1.1.4.2  yamt }
    250  1.1.1.1.4.2  yamt #endif /* HAVE_SYNC_BUILTINS */
    251  1.1.1.1.4.2  yamt 
    252  1.1.1.1.4.2  yamt 
    253  1.1.1.1.4.2  yamt /* This function implements the GUIDED scheduling method.  Arguments are
    254  1.1.1.1.4.2  yamt    as for gomp_iter_ull_static_next.  This function must be called with the
    255  1.1.1.1.4.2  yamt    work share lock held.  */
    256  1.1.1.1.4.2  yamt 
    257  1.1.1.1.4.2  yamt bool
    258  1.1.1.1.4.2  yamt gomp_iter_ull_guided_next_locked (gomp_ull *pstart, gomp_ull *pend)
    259  1.1.1.1.4.2  yamt {
    260  1.1.1.1.4.2  yamt   struct gomp_thread *thr = gomp_thread ();
    261  1.1.1.1.4.2  yamt   struct gomp_work_share *ws = thr->ts.work_share;
    262  1.1.1.1.4.2  yamt   struct gomp_team *team = thr->ts.team;
    263  1.1.1.1.4.2  yamt   gomp_ull nthreads = team ? team->nthreads : 1;
    264  1.1.1.1.4.2  yamt   gomp_ull n, q;
    265  1.1.1.1.4.2  yamt   gomp_ull start, end;
    266  1.1.1.1.4.2  yamt 
    267  1.1.1.1.4.2  yamt   if (ws->next_ull == ws->end_ull)
    268  1.1.1.1.4.2  yamt     return false;
    269  1.1.1.1.4.2  yamt 
    270  1.1.1.1.4.2  yamt   start = ws->next_ull;
    271  1.1.1.1.4.2  yamt   if (__builtin_expect (ws->mode, 0) == 0)
    272  1.1.1.1.4.2  yamt     n = (ws->end_ull - start) / ws->incr_ull;
    273  1.1.1.1.4.2  yamt   else
    274  1.1.1.1.4.2  yamt     n = (start - ws->end_ull) / -ws->incr_ull;
    275  1.1.1.1.4.2  yamt   q = (n + nthreads - 1) / nthreads;
    276  1.1.1.1.4.2  yamt 
    277  1.1.1.1.4.2  yamt   if (q < ws->chunk_size_ull)
    278  1.1.1.1.4.2  yamt     q = ws->chunk_size_ull;
    279  1.1.1.1.4.2  yamt   if (q <= n)
    280  1.1.1.1.4.2  yamt     end = start + q * ws->incr_ull;
    281  1.1.1.1.4.2  yamt   else
    282  1.1.1.1.4.2  yamt     end = ws->end_ull;
    283  1.1.1.1.4.2  yamt 
    284  1.1.1.1.4.2  yamt   ws->next_ull = end;
    285  1.1.1.1.4.2  yamt   *pstart = start;
    286  1.1.1.1.4.2  yamt   *pend = end;
    287  1.1.1.1.4.2  yamt   return true;
    288  1.1.1.1.4.2  yamt }
    289  1.1.1.1.4.2  yamt 
    290  1.1.1.1.4.2  yamt #if defined HAVE_SYNC_BUILTINS && defined __LP64__
    291  1.1.1.1.4.2  yamt /* Similar, but doesn't require the lock held, and uses compare-and-swap
    292  1.1.1.1.4.2  yamt    instead.  Note that the only memory value that changes is ws->next_ull.  */
    293  1.1.1.1.4.2  yamt 
    294  1.1.1.1.4.2  yamt bool
    295  1.1.1.1.4.2  yamt gomp_iter_ull_guided_next (gomp_ull *pstart, gomp_ull *pend)
    296  1.1.1.1.4.2  yamt {
    297  1.1.1.1.4.2  yamt   struct gomp_thread *thr = gomp_thread ();
    298  1.1.1.1.4.2  yamt   struct gomp_work_share *ws = thr->ts.work_share;
    299  1.1.1.1.4.2  yamt   struct gomp_team *team = thr->ts.team;
    300  1.1.1.1.4.2  yamt   gomp_ull nthreads = team ? team->nthreads : 1;
    301  1.1.1.1.4.2  yamt   gomp_ull start, end, nend, incr;
    302  1.1.1.1.4.2  yamt   gomp_ull chunk_size;
    303  1.1.1.1.4.2  yamt 
    304  1.1.1.1.4.2  yamt   start = ws->next_ull;
    305  1.1.1.1.4.2  yamt   end = ws->end_ull;
    306  1.1.1.1.4.2  yamt   incr = ws->incr_ull;
    307  1.1.1.1.4.2  yamt   chunk_size = ws->chunk_size_ull;
    308  1.1.1.1.4.2  yamt 
    309  1.1.1.1.4.2  yamt   while (1)
    310  1.1.1.1.4.2  yamt     {
    311  1.1.1.1.4.2  yamt       gomp_ull n, q;
    312  1.1.1.1.4.2  yamt       gomp_ull tmp;
    313  1.1.1.1.4.2  yamt 
    314  1.1.1.1.4.2  yamt       if (start == end)
    315  1.1.1.1.4.2  yamt 	return false;
    316  1.1.1.1.4.2  yamt 
    317  1.1.1.1.4.2  yamt       if (__builtin_expect (ws->mode, 0) == 0)
    318  1.1.1.1.4.2  yamt 	n = (end - start) / incr;
    319  1.1.1.1.4.2  yamt       else
    320  1.1.1.1.4.2  yamt 	n = (start - end) / -incr;
    321  1.1.1.1.4.2  yamt       q = (n + nthreads - 1) / nthreads;
    322  1.1.1.1.4.2  yamt 
    323  1.1.1.1.4.2  yamt       if (q < chunk_size)
    324  1.1.1.1.4.2  yamt 	q = chunk_size;
    325  1.1.1.1.4.2  yamt       if (__builtin_expect (q <= n, 1))
    326  1.1.1.1.4.2  yamt 	nend = start + q * incr;
    327  1.1.1.1.4.2  yamt       else
    328  1.1.1.1.4.2  yamt 	nend = end;
    329  1.1.1.1.4.2  yamt 
    330  1.1.1.1.4.2  yamt       tmp = __sync_val_compare_and_swap (&ws->next_ull, start, nend);
    331  1.1.1.1.4.2  yamt       if (__builtin_expect (tmp == start, 1))
    332  1.1.1.1.4.2  yamt 	break;
    333  1.1.1.1.4.2  yamt 
    334  1.1.1.1.4.2  yamt       start = tmp;
    335  1.1.1.1.4.2  yamt     }
    336  1.1.1.1.4.2  yamt 
    337  1.1.1.1.4.2  yamt   *pstart = start;
    338  1.1.1.1.4.2  yamt   *pend = nend;
    339  1.1.1.1.4.2  yamt   return true;
    340  1.1.1.1.4.2  yamt }
    341  1.1.1.1.4.2  yamt #endif /* HAVE_SYNC_BUILTINS */
    342