#---------------8<---[snip]--------------------------------------------------------------------------------- # create a permanent sleeping beauty process that sleeps 1/18.2th of second # every four times it gets scheduled, unless the do_not_sleep flag is set. # the do_not_sleep flag is meant to be set when a download is in progress, # so that the download throughput is not affected. #---------------8<---[snip]--------------------------------------------------------------------------------- --- a/src/usr/sleeping_beauty.c 1969-12-31 16:00:00.000000000 -0800 +++ b/src/usr/sleeping_beauty.c 2012-06-25 15:27:46.607097999 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 Embrane, Inc. . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include + + + +#define SLEEPING_FACTOR 4 + +static int do_not_sleep = 0; + +void prince_kisses_sleeping_beauty(void) { + do_not_sleep = 1; +} + +void sleeping_beauty_bites_the_apple(void) { + do_not_sleep = 0; +} + +/** + * Sleep every SLEEPING_FACTOR times + * + * @v process Network stack process + */ +static void sleeping_step ( struct process *process __unused ) { + static int countdown = 0; + + if ( 0 == countdown ) { + countdown = SLEEPING_FACTOR; + } + + if ( do_not_sleep || --countdown ) { + return; + } + + cpu_nap(); +} + +/* Sleeping beauty process */ +PERMANENT_PROCESS ( sleeping_beauty, sleeping_step ); #---------------8<---[snip]--------------------------------------------------------------------------------- # make two methods available to toggle the aggressive polling on and off: # # - prince_kisses_sleeping_beauty() <-- the beauty wakes up and polls agressively # # - sleeping_beauty_bites_the_apple() <-- the beauty falls asleep again and uses very little CPU # #---------------8<---[snip]--------------------------------------------------------------------------------- --- a/src/usr/sleeping_beauty.h 1969-12-31 16:00:00.000000000 -0800 +++ b/src/usr/sleeping_beauty.h 2012-06-25 15:27:17.118098360 -0700 @@ -0,0 +1,3 @@ +extern void prince_kisses_sleeping_beauty(void); + +extern void sleeping_beauty_bites_the_apple(void); #---------------8<---[snip]--------------------------------------------------------------------------------- # Detect when TCP connections stall, and fail the download, else from there # on we would be sucking the host CPU forever. #---------------8<---[snip]--------------------------------------------------------------------------------- diff --git a/src/core/monojob.c b/src/core/monojob.c index d2161b3..9bcb943 100644 --- a/src/core/monojob.c +++ b/src/core/monojob.c @@ -67,6 +67,8 @@ int monojob_wait ( const char *string ) { unsigned long completed; unsigned long total; unsigned int percentage; + unsigned long last_completed = 0; + unsigned int stalled_seconds = 0; int shown_percentage = 0; if ( string ) @@ -102,6 +104,15 @@ int monojob_wait ( const char *string ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); job_progress ( &monojob, &progress ); + if ( last_completed == progress.completed ) { + ++stalled_seconds; + } else { + stalled_seconds=0; + } + if ( stalled_seconds >= 30 ) { + monojob_close ( &monojob, -ETIME ); + break; + } /* Normalise progress figures to avoid overflow */ completed = ( progress.completed / 128 ); total = ( progress.total / 128 ); @@ -113,6 +124,7 @@ int monojob_wait ( const char *string ) { printf ( "." ); shown_percentage = 0; } + last_completed = progress.completed; last_progress = now; } } #---------------8<---[snip]--------------------------------------------------------------------------------- # Avoid using 100% CPU at all times (bad for virtualized environments). # When a download making progress, go back to aggressive polling #---------------8<---[snip]--------------------------------------------------------------------------------- diff -u b/src/core/monojob.c b/src/core/monojob.c --- a/src/core/monojob.c +++ b/src/core/monojob.c @@ -27,6 +27,7 @@ #include #include #include +#include /** @file * @@ -104,6 +105,9 @@ if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); job_progress ( &monojob, &progress ); + if ( progress.completed && !last_completed ) { + prince_kisses_sleeping_beauty(); + } if ( last_completed == progress.completed ) { ++stalled_seconds; } else { #---------------8<---[snip]--------------------------------------------------------------------------------- # Avoid using 100% CPU at all times (bad for virtualized environments). # When a download fails, go back to moderate polling #---------------8<---[snip]--------------------------------------------------------------------------------- --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -396,6 +397,9 @@ int netboot ( struct net_device *netdev ) { err_pxe_menu_boot: err_dhcp: err_ifopen: + + sleeping_beauty_bites_the_apple(); + return rc; } #---------------8<---[snip]---------------------------------------------------------------------------------