Branch: Tag:

2010-02-18

2010-02-18 14:50:41 by Stephen R. van den Berg <srb@cuci.nl>

Simplify and reduce sleep functions, use nanosleep when available.

Rev: src/builtin_functions.c:1.696
Rev: src/port.c:1.89
Rev: src/port.h:1.68
Rev: src/post_modules/SQLite/sqlite.cmod:1.30
Rev: src/threads.c:1.282

2:   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: builtin_functions.c,v 1.695 2009/11/11 20:22:19 mast Exp $ + || $Id: builtin_functions.c,v 1.696 2010/02/18 14:50:41 srb Exp $   */      #include "global.h"
4397:   #undef HAVE_POLL   #endif    - /*! @decl void sleep(int|float s, void|int abort_on_signal) -  *! -  *! This function makes the program stop for @[s] seconds. -  *! -  *! Only signal handlers can interrupt the sleep, and only when -  *! @[abort_on_signal] is set. If more than one thread is running -  *! the signal must be sent to the sleeping thread. Other callbacks -  *! are not called during sleep. -  *! -  *! If @[s] is zero then this thread will yield to other threads but -  *! not sleep otherwise. Note that Pike yields internally at regular -  *! intervals so it's normally not necessary to do this. -  *! -  *! @seealso -  *! @[signal()], @[delay()] -  */ - PMOD_EXPORT void f_sleep(INT32 args) + static void delaysleep(double delay, unsigned do_abort_on_signal, +  unsigned do_microsleep)   { -  + #define POLL_SLEEP_LIMIT 0.02 +    #ifdef HAVE_GETHRTIME    hrtime_t t0,tv;   #else    struct timeval t0,tv;   #endif    -  double delay=0.0; -  int do_abort_on_signal; +  /* Special case, sleep(0) means 'yield' */ +  if(delay == 0.0) +  { +  check_threads_etc(); +  return; +  }    -  +  if(sizeof(FLOAT_TYPE)<sizeof(double)) +  delay += FLT_EPSILON*5; /* round up */ +    #ifdef HAVE_GETHRTIME    t0=tv=gethrtime();   #define GET_TIME_ELAPSED tv=gethrtime()
4437:      #define FIX_LEFT() \    GET_TIME_ELAPSED; \ -  left = delay - TIME_ELAPSED; +  left = delay - TIME_ELAPSED; \ +  if (do_microsleep) left-=POLL_SLEEP_LIMIT;    -  switch(Pike_sp[-args].type) +  if (!do_microsleep || delay>POLL_SLEEP_LIMIT)    { -  case T_INT: -  delay=(double)Pike_sp[-args].u.integer; -  break; -  -  case T_FLOAT: -  delay=(double)Pike_sp[-args].u.float_number; -  break; -  } -  -  /* Special case, sleep(0) means 'yield' */ -  if(delay == 0.0) +  for(;;)    { -  check_threads_etc(); -  pop_n_elems(args); -  return; -  } -  -  if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp + 1-args)) -  { -  do_abort_on_signal=1; -  }else{ -  do_abort_on_signal=0; -  } -  -  pop_n_elems(args); -  -  while(1) -  { +     double left;    /* THREADS_ALLOW may take longer time then POLL_SLEEP_LIMIT */    THREADS_ALLOW(); -  do { +     FIX_LEFT(); -  if(left<=0.0) break; -  - #ifdef __NT__ -  Sleep(DO_NOT_WARN((int)(left*1000))); - #elif defined(HAVE_POLL) -  { -  /* MacOS X is stupid, and requires a non-NULL pollfd pointer. */ -  struct pollfd sentinel; -  poll(&sentinel, 0, (int)(left*1000)); +  if(left>0.0) +  sysleep(left); +  THREADS_DISALLOW(); +  if(do_abort_on_signal) +  return; +  FIX_LEFT(); +  if(left<=0.0) +  break; +  check_threads_etc();    } - #else -  { -  struct timeval t3; -  t3.tv_sec=left; -  t3.tv_usec=(int)((left - (int)left)*1e6); -  select(0,0,0,0,&t3); +     } - #endif -  } while(0); -  THREADS_DISALLOW(); +     -  if(do_abort_on_signal) return; +  if (do_microsleep) +  while (delay>TIME_ELAPSED) +  GET_TIME_ELAPSED; + }    -  FIX_LEFT(); + /*! @decl void sleep(int|float s, void|int abort_on_signal) +  *! +  *! This function makes the program stop for @[s] seconds. +  *! +  *! Only signal handlers can interrupt the sleep, and only when +  *! @[abort_on_signal] is set. If more than one thread is running +  *! the signal must be sent to the sleeping thread. Other callbacks +  *! are not called during sleep. +  *! +  *! If @[s] is zero then this thread will yield to other threads but +  *! not sleep otherwise. Note that Pike yields internally at regular +  *! intervals so it's normally not necessary to do this. +  *! +  *! @seealso +  *! @[signal()], @[delay()] +  */ + PMOD_EXPORT void f_sleep(INT32 args) + { +  double delay=0.0; +  unsigned do_abort_on_signal;    -  if(left<=0.0) +  switch(Pike_sp[-args].type)    { -  +  case T_INT: +  delay=(double)Pike_sp[-args].u.integer;    break; -  }else{ -  check_threads_etc(); +  +  case T_FLOAT: +  delay=(double)Pike_sp[-args].u.float_number; +  break;    } -  +  +  do_abort_on_signal = delay!=0.0 && args > 1 +  && !UNSAFE_IS_ZERO(Pike_sp + 1-args); +  pop_n_elems(args); +  +  delaysleep(delay, do_abort_on_signal, 0);   } - } +       #undef FIX_LEFT   #undef GET_TIME_ELAPSED
4525:    */   PMOD_EXPORT void f_delay(INT32 args)   { - #define POLL_SLEEP_LIMIT 0.02 -  - #ifdef HAVE_GETHRTIME -  hrtime_t t0,tv; - #else -  struct timeval t0,tv; - #endif -  +     double delay=0.0; -  int do_microsleep; -  int do_abort_on_signal; +  unsigned do_abort_on_signal;    - #ifdef HAVE_GETHRTIME -  t0=tv=gethrtime(); - #define GET_TIME_ELAPSED tv=gethrtime() - #define TIME_ELAPSED (tv-t0)*1e-9 - #else -  GETTIMEOFDAY(&t0); -  tv=t0; - #define GET_TIME_ELAPSED GETTIMEOFDAY(&tv) - #define TIME_ELAPSED ((tv.tv_sec-t0.tv_sec) + (tv.tv_usec-t0.tv_usec)*1e-6) - #endif -  - #define FIX_LEFT() \ -  GET_TIME_ELAPSED; \ -  left = delay - TIME_ELAPSED; \ -  if (do_microsleep) left-=POLL_SLEEP_LIMIT; -  +     switch(Pike_sp[-args].type)    {    case T_INT:
4564:    break;    }    -  /* Special case, sleep(0) means 'yield' */ -  if(delay == 0.0) -  { -  check_threads_etc(); +  do_abort_on_signal = delay!=0.0 && args > 1 +  && !UNSAFE_IS_ZERO(Pike_sp + 1-args);    pop_n_elems(args); -  return; -  } +     -  if(args > 1 && !UNSAFE_IS_ZERO(Pike_sp + 1-args)) -  { -  do_microsleep=0; -  do_abort_on_signal=1; -  }else{ -  do_microsleep=delay<10; -  do_abort_on_signal=0; +  delaysleep(delay, do_abort_on_signal, !do_abort_on_signal && delay<10);   }    -  pop_n_elems(args); -  -  if (delay>POLL_SLEEP_LIMIT || !do_microsleep) -  { -  while(1) -  { -  double left; -  /* THREADS_ALLOW may take longer time then POLL_SLEEP_LIMIT */ -  THREADS_ALLOW(); -  do { -  FIX_LEFT(); -  if(left<=0.0) break; -  - #ifdef __NT__ -  Sleep(DO_NOT_WARN((int)(left*1000))); - #elif defined(HAVE_POLL) -  { -  /* MacOS X is stupid, and requires a non-NULL pollfd pointer. */ -  struct pollfd sentinel; -  poll(&sentinel, 0, (int)(left*1000)); -  } - #else -  { -  struct timeval t3; -  t3.tv_sec=left; -  t3.tv_usec=(int)((left - (int)left)*1e6); -  select(0,0,0,0,&t3); -  } - #endif -  } while(0); -  THREADS_DISALLOW(); -  -  if(do_abort_on_signal) return; -  -  FIX_LEFT(); -  -  if(left<=0.0) -  { -  break; -  }else{ -  check_threads_etc(); -  } -  } -  } -  -  if (do_microsleep) -  while (delay>TIME_ELAPSED) -  GET_TIME_ELAPSED; - } -  +    /*! @decl int gc()    *!    *! Force garbage collection.