Skip to content

Commit 87d04ed

Browse files
committed
Fix usleep() bug causing excessive host CPU consumption:
The root cause of the bug was in my incorrect #define of MAX_TOD_UPDATE_USECS in featall.h, which was #defined to 1000000 (one million) instead of 999999, thereby causing the TXF rubato_thread to do a usleep for 1000000 (one million) microseconds, which, being invalid, was causing it to not sleep at all and instead return immediately with an error, causing it to loop continuously without sleeping, consuming all available host CPU due to the timer threads being the highest priority thread in Hercules. comm3705.c also had a similar bug wherein it was using "min(1000000,delay)" for one of its usleep(). In addition to fixing the previously mentioned bug, I have also introduced a new USLEEP() macro which calls a new "herc_usleep()" function that will report any usleep() error that might occur. (I purposely did not code it to fix (hide) the problem but rather to just report it so that the caller can thus be fixed to not make invalid usleep calls.) This should close GitHub Issue #589 "Auxiliary threads eating up CPU time" as well as the long running "CPU utilization on Raspberry Pi" thread that took place in the main Hercules group recently.
1 parent cddce71 commit 87d04ed

35 files changed

+85
-65
lines changed

cckddasd.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ int rc, i; /* Return code, Loop index */
310310
while (cckd->ras)
311311
{
312312
release_lock(&cckdblk.ralock);
313-
usleep(1);
313+
USLEEP(1);
314314
obtain_lock(&cckdblk.ralock);
315315
}
316316
release_lock(&cckdblk.ralock);

cckddasd64.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ int rc, i; /* Return code, Loop index */
140140
while (cckd->ras)
141141
{
142142
release_lock(&cckdblk.ralock);
143-
usleep(1);
143+
USLEEP(1);
144144
obtain_lock(&cckdblk.ralock);
145145
}
146146
release_lock(&cckdblk.ralock);

cgibin.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ int msgcount = 22;
280280
panel_command(command);
281281
// Wait a bit before proceeding in case
282282
// the command issues a lot of messages
283-
usleep(50000);
283+
USLEEP(50000);
284284
}
285285

286286
if((value = cgi_variable(webblk,"msgcount")))
@@ -1623,7 +1623,7 @@ void cgibin_api_v1_syslog(WEBBLK *webblk)
16231623
panel_command(command);
16241624
// Wait a bit before proceeding in case
16251625
// the command issues a lot of messages
1626-
usleep(50000);
1626+
USLEEP(50000);
16271627
hprintf(webblk->sock,"{\"command\": \"%s\",",command);
16281628
}
16291629
else

channel.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ typedef struct PREFETCH PREFETCH;
338338
#define IODELAY(_dev) \
339339
do { \
340340
if (sysblk.iodelay > 0 && (_dev)->devchar[10] == 0x20) \
341-
usleep(sysblk.iodelay); \
341+
USLEEP(sysblk.iodelay); \
342342
} while(0)
343343
#else
344344
#define IODELAY(_dev)
@@ -4151,7 +4151,7 @@ do { \
41514151
#ifdef FEATURE_S370_CHANNEL
41524152
if (dev->devtype == 0x2703)
41534153
if (dev->commadpt->lnctl == COMMADPT_LNCTL_ASYNC)
4154-
usleep(5000);
4154+
USLEEP(5000);
41554155
#endif
41564156

41574157
#if DEBUG_DUMP

cmdtab.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1828,7 +1828,8 @@
18281828
"When the z/Arch Transactional-Execution Facility *is* installed and\n" \
18291829
"enabled the minimum and default intervals are 200 and 400 microseconds.\n" \
18301830
"\n" \
1831-
"The maximum allowed interval is 1000000 microseconds (one second).\n" \
1831+
"The maximum allowed interval is "QSTR( MAX_TOD_UPDATE_USECS )" microseconds (one microsecond\n" \
1832+
"less than one second).\n" \
18321833
"\n" \
18331834
"Also note that due to host system limitations and/or design, some\n" \
18341835
"hosts may round up and/or coalesce short microsecond intervals to a\n" \

comm3705.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ static void *telnet_thread(void *vca)
11581158
ca->hangup = 0;
11591159
for (;;)
11601160
{
1161-
usleep(50000);
1161+
USLEEP(50000);
11621162
if (ca->hangup)
11631163
break;
11641164
/* read_socket has changed from 3.04 to 3.06 - we need old way */
@@ -1224,7 +1224,7 @@ static void *commadpt_thread(void *vca)
12241224
release_lock(&ca->lock);
12251225
if(ca->ackspeed == 0) delay = 50000 + (ca->unack_attn_count * 100000); /* Max's reliable algorithm */
12261226
else delay = (ca->unack_attn_count * ca->unack_attn_count + 1) * ca->ackspeed; /* much faster but TCAM hates it */
1227-
usleep(min(1000000,delay)); /* go to sleep, max. 1 second */
1227+
USLEEP(min((int)(ONE_MILLION-1),delay)); /* go to sleep, max. 1 second */
12281228
obtain_lock(&ca->lock);
12291229
make_sna_requests2(ca);
12301230
make_sna_requests3(ca);

commadpt.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ static void *commadpt_thread(void *vca)
14741474
if(ca->inbfr.havedata || ca->eol_flag)
14751475
{
14761476
if (ca->term == COMMADPT_TERM_2741) {
1477-
usleep(10000);
1477+
USLEEP(10000);
14781478
}
14791479
ca->curpending=COMMADPT_PEND_IDLE;
14801480
signal_condition(&ca->ipc);

console.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3632,7 +3632,7 @@ int prev_rlen3270;
36323632
{
36333633
// "COMM: pselect() failed: %s"
36343634
CONERROR( HHC90508, "D", strerror( select_errno ));
3635-
usleep( 50000 ); // (wait a bit; maybe it'll fix itself??)
3635+
USLEEP( 50000 ); // (wait a bit; maybe it'll fix itself??)
36363636
}
36373637
continue;
36383638

@@ -3696,7 +3696,7 @@ int prev_rlen3270;
36963696
{
36973697
// "COMM: accept() failed: %s"
36983698
CONERROR( HHC90509, "D", strerror( accept_errno ));
3699-
usleep( 50000 ); // (wait a bit; maybe it'll fix itself??)
3699+
USLEEP( 50000 ); // (wait a bit; maybe it'll fix itself??)
37003700
}
37013701
continue;
37023702
}

ctc_ctci.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ static void* CTCI_ReadThread( void* arg )
10921092
// Don't use sched_yield() here; use an actual non-dispatchable
10931093
// delay instead so as to allow another [possibly lower priority]
10941094
// thread to 'read' (remove) some packet(s) from our frame buffer.
1095-
usleep( CTC_DELAY_USECS ); // (wait a bit before retrying...)
1095+
USLEEP( CTC_DELAY_USECS ); // (wait a bit before retrying...)
10961096
}
10971097
}
10981098

ctc_lcs.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,7 @@ static void UpdatePortStarted( int bStarted, DEVBLK* pDEVBLK, PLCSPORT pLCSPORT
16911691
release_lock( &pLCSPORT->PortEventLock );
16921692

16931693
PTT_DEBUG( "UPDTPORT pause 150", 000, pDEVBLK->devnum, pLCSPORT->bPort );
1694-
usleep( 150*1000 );
1694+
USLEEP( 150*1000 );
16951695
}
16961696

16971697
// ====================================================================
@@ -2191,7 +2191,7 @@ static void LCS_EnqueueReplyFrame( PLCSDEV pLCSDEV, PLCSCMDHDR pReply, size_t iS
21912191
// Wait for LCS_Read to empty the buffer...
21922192

21932193
ASSERT( ENOBUFS == errno );
2194-
usleep( CTC_DELAY_USECS );
2194+
USLEEP( CTC_DELAY_USECS );
21952195
}
21962196
PTT_TIMING( "af repNQ", 0, iSize, 0 );
21972197
PTT_DEBUG( "ENQ RepFrame EXIT ", pReply->bCmdCode, pDEVBLK->devnum, bPort );
@@ -2798,7 +2798,7 @@ static void LCS_EnqueueEthFrame( PLCSPORT pLCSPORT, PLCSDEV pLCSDEV, BYTE* pData
27982798
// Wait for LCS_Read to empty the buffer...
27992799

28002800
ASSERT( ENOBUFS == errno );
2801-
usleep( CTC_DELAY_USECS );
2801+
USLEEP( CTC_DELAY_USECS );
28022802
}
28032803
PTT_TIMING( "af enqueue", 0, iSize, 0 );
28042804
PTT_DEBUG( "ENQ EthFrame EXIT ", 000, pDEVBLK->devnum, bPort );
@@ -4150,7 +4150,7 @@ static void* LCS_AttnThread( void* arg)
41504150
{
41514151

41524152
// Wait a small (but increasing) amount of time.
4153-
usleep(interval);
4153+
USLEEP(interval);
41544154

41554155
//?? // is there still something in our frame buffer?
41564156
//?? if (!pLCSDEV->fDataPending && !pLCSDEV->fReplyPending)

ctc_ptp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,7 @@ void* ptp_read_thread( void* arg )
22632263
// Don't use schedyield() here; use an actual non-dispatchable
22642264
// delay instead so as to allow another [possibly lower priority]
22652265
// thread to 'read' (remove) the packet(s) from the read buffer.
2266-
usleep( PTP_DELAY_USECS ); // (wait a bit before retrying...)
2266+
USLEEP( PTP_DELAY_USECS ); // (wait a bit before retrying...)
22672267

22682268
continue;
22692269

ctcadpt.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ static int CTCE_Init( DEVBLK *dev, int argc, char *argv[] )
19291929
dev->allocated = 0;
19301930
RELEASE_DEVLOCK( dev );
19311931
{
1932-
usleep( 700000 );
1932+
USLEEP( 700000 );
19331933
}
19341934
OBTAIN_DEVLOCK( dev );
19351935
dev->allocated = 1;
@@ -2945,7 +2945,7 @@ static void* CTCE_RecvThread( void* argp )
29452945
{
29462946
CTCE_Info.de_ready_attn_rc = device_attention( pDEVBLK, CSW_DE );
29472947
}
2948-
while ((CTCE_Info.de_ready_attn_rc == 3) && (usleep( 100 ) == 0));
2948+
while ((CTCE_Info.de_ready_attn_rc == 3) && (USLEEP( 100 ) == 0));
29492949
}
29502950
OBTAIN_DEVLOCK( pDEVBLK );
29512951

@@ -2995,7 +2995,7 @@ static void* CTCE_RecvThread( void* argp )
29952995
// which needs to be configured using the CTCE option ATTNDELAY <nnn>
29962996
if( pDEVBLK->ctce_attn_delay && CTCE_Info.busy_waits == 0 )
29972997
{
2998-
usleep( pDEVBLK->ctce_attn_delay );
2998+
USLEEP( pDEVBLK->ctce_attn_delay );
29992999
}
30003000

30013001
CTCE_Info.working_attn_rc = device_attention( pDEVBLK, CSW_ATTN );
@@ -3014,7 +3014,7 @@ static void* CTCE_RecvThread( void* argp )
30143014
{
30153015
i = i * 2;
30163016
}
3017-
usleep(i);
3017+
USLEEP(i);
30183018

30193019
// Cancel the ATTN in case a CCW program
30203020
// has started in the mean time.
@@ -3632,7 +3632,7 @@ static void* CTCE_ConnectThread( void* argp )
36323632
if ( rc < 0 )
36333633
{
36343634
close_socket( fd );
3635-
usleep(connect_retry_interval * 1000) ;
3635+
USLEEP(connect_retry_interval * 1000) ;
36363636
}
36373637
OBTAIN_DEVLOCK( dev );
36383638

dasdconv.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ static void delayed_exit (int exit_code)
195195
{
196196
/* Delay exiting is to give the system
197197
* time to display the error message. */
198-
usleep(100000);
198+
USLEEP(100000);
199199
exit(exit_code);
200200
}
201201

dasdconv64.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ static void delayed_exit (int exit_code)
194194
{
195195
/* Delay exiting is to give the system
196196
* time to display the error message. */
197-
usleep(100000);
197+
USLEEP(100000);
198198
exit(exit_code);
199199
}
200200

diagnose.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ U32 code;
877877
for (i=0; i < secs; ++i)
878878
SLEEP(1); /* (sleep one second at a time) */
879879
if (usecs)
880-
usleep(usecs); /* (remaining microseconds, if any) */
880+
USLEEP(usecs); /* (remaining microseconds, if any) */
881881
break;
882882
}
883883

dyngui.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,7 @@ HDL_FINAL_SECTION
21772177
if (sysblk.shutdown)
21782178
{
21792179
bDoneProcessing = TRUE; // (tell main loop to stop processing)
2180-
usleep(100000); // (brief delay to give GUI time
2180+
USLEEP(100000); // (brief delay to give GUI time
21812181
// to display ALL shutdown msgs)
21822182
}
21832183
}

featall.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070

7171
#define MIN_TOD_UPDATE_USECS 50 /* Min TOD updt freq (usecs) */
7272
#define DEF_TOD_UPDATE_USECS 50 /* Def TOD updt freq (usecs) */
73-
#define MAX_TOD_UPDATE_USECS 1000000 /* Max TOD updt freq (usecs) */
73+
#define MAX_TOD_UPDATE_USECS 999999 /* Max TOD updt freq (usecs) */
7474

7575
#define MAX_DEVICE_THREAD_IDLE_SECS 300 /* 5 Minute thread timeout */
7676
//efine OPTION_LONG_HOSTINFO /* Detailed host & logo info */

hao.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ static void* hao_thread(void* dummy)
611611
// "HAO thread waiting for logger facility to become active"
612612
WRMSG( HHC00090, "W" );
613613
}
614-
usleep( 50 * 1000 ); /* (wait for a bit) */
614+
USLEEP( 50 * 1000 ); /* (wait for a bit) */
615615
}
616616

617617
if (!sysblk.shutdown && did_waiting_msg)

hsccmd.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ static void* quit_thread( void* arg )
745745
// messages at least twice to ensure that the "exit"
746746
// command has time to be echoed to the screen.
747747

748-
usleep( quitdelay_usecs );
748+
USLEEP( quitdelay_usecs );
749749

750750
// Now proceed with a normal shutdown, which waits for
751751
// the guest to quiesce itself beforehand (if appropriate)
@@ -1987,7 +1987,7 @@ static void try_scsi_refresh( DEVBLK* dev )
19871987
gen_parms.dev = dev;
19881988

19891989
VERIFY( dev->tmh->generic( &gen_parms ) == 0 ); // (maybe update status)
1990-
usleep( 10 * 1000 ); // (let thread start/end)
1990+
USLEEP( 10 * 1000 ); // (let thread start/end)
19911991
}
19921992

19931993
/*-------------------------------------------------------------------*/
@@ -7536,7 +7536,7 @@ char **save_argv = NULL;
75367536
|| (dev->scsw.flag3 & SCSW3_SC_PEND)))
75377537
{
75387538
RELEASE_DEVLOCK( dev );
7539-
usleep(5000);
7539+
USLEEP(5000);
75407540
OBTAIN_DEVLOCK( dev );
75417541
}
75427542
}

hscmisc.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,7 @@ static void do_shutdown_now()
14551455
// (hack to prevent minor message glitch during shutdown)
14561456
fflush( stdout );
14571457
fflush( stderr );
1458-
usleep( 10000 );
1458+
USLEEP( 10000 );
14591459

14601460
ASSERT( !sysblk.shutfini ); // (sanity check)
14611461
sysblk.shutfini = FALSE; // (shutdown NOT finished yet)
@@ -1467,7 +1467,7 @@ static void do_shutdown_now()
14671467
for (n=0; sysblk.devtnbr && n < 100; ++n)
14681468
{
14691469
signal_condition( &sysblk.ioqcond );
1470-
usleep( 10000 );
1470+
USLEEP( 10000 );
14711471
}
14721472
}
14731473

@@ -1477,7 +1477,7 @@ static void do_shutdown_now()
14771477
// (hack to prevent minor message glitch during shutdown)
14781478
fflush( stdout );
14791479
fflush( stderr );
1480-
usleep( 10000 );
1480+
USLEEP( 10000 );
14811481

14821482
#if !defined( _MSVC_ )
14831483
logger_unredirect();

hscutl.c

+15
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,21 @@ DLL_EXPORT void list_all_symbols()
604604
WRMSG( HHC02199, "I", tok->var, tok->val ? tok->val : "" );
605605
}
606606

607+
/* Hercules microsecond sleep */
608+
DLL_EXPORT int herc_usleep( useconds_t usecs )
609+
{
610+
int rc;
611+
if ((rc = usleep( usecs )) != 0)
612+
{
613+
int save_errno = errno;
614+
// "Error in function %s: %s"
615+
WRMSG( HHC00075, "E", "usleep()", strerror( save_errno ));
616+
errno = save_errno;
617+
rc = -1;
618+
}
619+
return rc;
620+
}
621+
607622
/* Subtract 'beg_timeval' from 'end_timeval' yielding 'dif_timeval' */
608623
/* Return code: success == 0, error == -1 (difference was negative) */
609624

hscutl.h

+3
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ strlcat(char *dst, const char *src, size_t siz);
154154
#define STRLCPY( dst, src ) strlcpy( (dst), (src), sizeof(dst) )
155155
#define STRLCAT( dst, src ) strlcat( (dst), (src), sizeof(dst) )
156156

157+
#define USLEEP( _u ) herc_usleep( _u )
158+
HUT_DLL_IMPORT int herc_usleep( useconds_t usecs );
159+
157160
/* Subtract/add gettimeofday struct timeval */
158161
HUT_DLL_IMPORT int timeval_subtract (struct timeval *beg_timeval, struct timeval *end_timeval, struct timeval *dif_timeval);
159162
HUT_DLL_IMPORT int timeval_add (struct timeval *dif_timeval, struct timeval *accum_timeval);

html/hercconf.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -1620,7 +1620,8 @@ <h3>System parameters</h3>
16201620
When the z/Architecure Transactional-Execution Facility <i><u>is</u></i> installed and
16211621
enabled, the minimum and default intervals are 200 and 400 microseconds.
16221622
<p>
1623-
The maximum allowed interval is 1000000 microseconds (one second).
1623+
The maximum allowed interval is 999999 microseconds
1624+
(one microsecond less than one second).
16241625
<p>
16251626
Also note that due to host system limitations and/or design, some
16261627
hosts may round up and/or

0 commit comments

Comments
 (0)