0

I'm writing a Windows service in C, using the classic example found here: https://learn.microsoft.com/en-us/windows/desktop/Services/svc-cpp. I'm trying to understand why CPU usage of my service is 25% when it is not doing anything.

I have taken out just about all of my code, leaving only the original skeleton program. Basically it is in a tight loop where it checks for the service stop command, then a Sleep(0), then loops back. In my real code, I am listening for a tcp connection, but that is out of the equation in this test.

VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
// initialization code not shown here

// Main loop
while(TRUE) {

// Check whether to stop the service.

ret=WaitForSingleObject(ghSvcStopEvent, 0);
if (ret == 0) {
  com_Log("Stop command received from service manager");
  break;
}

Sleep(0);

// This is where the service looks for work to do, but disabled for 
 testing

}

// shutdown code here

}

I thought the Sleep(0) is what returns control to the operating system, so why would this code be misbehaving and taking up such a big chunk of CPU?

Jeff McKay
  • 161
  • 2
  • 16
  • 1
    What do you expect [Sleep(0;)](https://learn.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-sleep) actually to do in throttling your service? – πάντα ῥεῖ Jan 15 '19 at 18:44
  • Sleeping hasn't returned control the operating system since Windows 95 when pre-emptive multitasking arrived. It just sleeps your process or thread, nothing more. The operating system is always in control. – tadman Jan 15 '19 at 19:14
  • 2
    Instead of using `Sleep` at all, just pass a non-zero value for the second argument to [`WaitForSingleObject`](https://learn.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject) and perform your service's work when it returns `WAIT_TIMEOUT`. Determine the timeout from your service's required response time. A timeout of around 200 milliseconds should be sufficient, and you could easily increase that. – paddy Jan 15 '19 at 19:16

1 Answers1

0

Sleep(0) was already discussed here.

Since you will have your cpu do nothing (23%) this function will return immediately. Try to replace it with something like Sleep(value) (value in miliseconds) to actually decrease your cpu usage.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Phisn
  • 861
  • 8
  • 18
  • 3
    Or better yet, put it to sleep in some *blocking* function that won't actually return until there's something to do - like `select`, `poll`, `WaitForMultipleObjects` or similar.. I mean, like any *sensible* event loop would do. Even if you `Sleep` for "some amount of time" you are still effectively "busy waiting" since your process *will* get woken up to do nothing whenever the timer expires - you don't want that. `Sleep(42)` is just a *hack* that *seems* to help. It's *not* a proper solution. – Jesper Juhl Jan 15 '19 at 19:07
  • 1
    @JesperJuhl yes, if the OP is waiting on a network connection, then [`select`](https://learn.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-select) with a timeout would be the appropriate choice. In that case, the timeout would represent the period at which to poll for the shutdown event, which could be large, (i.e 1 or 2 seconds). – paddy Jan 15 '19 at 19:22
  • @paddy Or, waiting for a timer or some other (whatever) event. A network event is far from the only thing one should block waiting for. And one can be blocked waiting for one of *multiple* events to happen. – Jesper Juhl Jan 15 '19 at 19:35