diff --git a/checkin_notes b/checkin_notes index 448c9b79de..c1299baec4 100755 --- a/checkin_notes +++ b/checkin_notes @@ -6206,3 +6206,12 @@ Karl 2003/09/05 Sched/ handle_request.C + +David Sept 6 2003 + - fixed bug where do_select wasn't sleeping + when there are no fds (doh!!) + + client/ + net_xfer.C,h + lib/ + util.C diff --git a/client/net_xfer.C b/client/net_xfer.C index 00e95151c5..3351d249a0 100644 --- a/client/net_xfer.C +++ b/client/net_xfer.C @@ -296,13 +296,11 @@ int NET_XFER_SET::remove(NET_XFER* nxp) { bool NET_XFER_SET::poll() { double bytes_xferred; int retval; - struct timeval timeout; time_t t = time(0); bool action = false; while (1) { - timeout.tv_sec = timeout.tv_usec = 0; - retval = do_select(bytes_xferred, timeout); + retval = do_select(bytes_xferred, 0); if (retval) break; if (bytes_xferred == 0) break; action = true; @@ -311,6 +309,11 @@ bool NET_XFER_SET::poll() { return action; } +static void double_to_timeval(double x, timeval& t) { + t.tv_sec = (int)x; + t.tv_usec = (int)(1000000*(x - (int)x)); +} + // Wait at most x seconds for network I/O to become possible, // then do up to about .5 seconds of I/O. // This is used only by the cmdline client, to sleep without slowing down I/O. @@ -318,11 +321,8 @@ bool NET_XFER_SET::poll() { int NET_XFER_SET::net_sleep(double x) { int retval; double bytes_xferred; - struct timeval timeout; - timeout.tv_sec = (int)x; - timeout.tv_usec = (int)(1000000*(x - (int)x)); - retval = do_select(bytes_xferred, timeout); + retval = do_select(bytes_xferred, x); if (retval) return retval; if (bytes_xferred) { return poll(); @@ -334,10 +334,11 @@ int NET_XFER_SET::net_sleep(double x) { // then do I/O on as many sockets as possible, subject to rate limits // Transfer at most one block per socket. // -int NET_XFER_SET::do_select(double& bytes_transferred, timeval& timeout) { +int NET_XFER_SET::do_select(double& bytes_transferred, double timeout) { int n, fd, retval, nsocks_queried; socklen_t i; NET_XFER *nxp; + struct timeval tv; ScopeMessages scope_messages(log_messages, ClientMessages::DEBUG_NET_XFER); @@ -387,8 +388,13 @@ int NET_XFER_SET::do_select(double& bytes_transferred, timeval& timeout) { } FD_SET(nxp->socket, &error_fds); } - if (nsocks_queried==0) return 0; - n = select(FD_SETSIZE, &read_fds, &write_fds, &error_fds, &timeout); + if (nsocks_queried==0) { + boinc_sleep(timeout); + return 0; + } + + double_to_timeval(timeout, tv); + n = select(FD_SETSIZE, &read_fds, &write_fds, &error_fds, &tv); scope_messages.printf( "NET_XFER_SET::do_select(): queried %d, returned %d\n", nsocks_queried, n diff --git a/client/net_xfer.h b/client/net_xfer.h index bea57314bb..bb80ecfe80 100644 --- a/client/net_xfer.h +++ b/client/net_xfer.h @@ -89,7 +89,7 @@ public: int remove(NET_XFER*); bool poll(); int net_sleep(double); - int do_select(double& bytes_transferred, struct timeval& timeout); + int do_select(double& bytes_transferred, double timeout); NET_XFER* lookup_fd(int); // lookup by fd void check_active(bool&, bool&); }; diff --git a/doc/api.php b/doc/api.php index 642645b950..f12a8fb9a1 100644 --- a/doc/api.php +++ b/doc/api.php @@ -35,7 +35,6 @@ For example, instead of

the application might use -

     char resolved_name[256];
     retval = boinc_resolve_filename(\"my_file\", resolved_name);
@@ -70,8 +69,16 @@ then call
 
     void boinc_checkpoint_completed();
 
-A call to boinc_time_to_checkpoint() is extremely fast, -so there is little penalty in calling it frequently. +boinc_time_to_checkpoint() is fast +(it usually makes no system calls), +so can be called frequently (hundreds or thousands of times a second). + +

+boinc_time_to_checkpoint() performs other time-based functions; +e.g. it periodically measures the application's CPU time and +reports it to the core client. +So, even for applications that don't do checkpointing, +it should be called at least once a second.

Atomic file update

@@ -111,14 +118,13 @@ This is done using

Communicating with the core client

The core client GUI displays the percent done of workunits in progress. -To keep this display current, an application should -periodically call +To keep this display current, an application should periodically call

    boinc_fraction_done(double fraction_done);
 
The fraction_done argument is a rough estimate of the workunit fraction complete (0 to 1). -This function is extremely fast and can be called often. +This function is fast and can be called frequently.

The following functions get information from the core client; @@ -150,7 +156,7 @@ list_item("team_expavg_credit", " team's recent average work per day."); list_end(); echo "

-It may call +An application may call

     int boinc_cpu_time(double &cpu_time, double& working_set_size);
 
diff --git a/lib/util.C b/lib/util.C index 9889e6c437..fcfd576697 100755 --- a/lib/util.C +++ b/lib/util.C @@ -175,7 +175,8 @@ void boinc_sleep(double seconds) { ::Sleep((int)(1000*seconds)); #else sleep((int)seconds); - usleep((int)fmod(seconds*1000000,1000000)); + int x = (int)fmod(seconds*1000000,1000000); + if (x) usleep(x); #endif }