Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread is always fully running. #497

Open
testdrive-profiling-master opened this issue Oct 11, 2024 · 14 comments
Open

Thread is always fully running. #497

testdrive-profiling-master opened this issue Oct 11, 2024 · 14 comments
Labels
bug Something isn't working

Comments

@testdrive-profiling-master
Copy link
Contributor

testdrive-profiling-master commented Oct 11, 2024

I've noticed that recent webui operations are taking up a lot of CPU resource on Windows.
Even a very simple examples/C/minimal project shows high CPU resource consumption.
Maybe the mutex inside the thread is behaving weirdly, is it ok on other OS?

I found following code is fully running without any hangs.

webui/src/webui.c

Lines 8514 to 8526 in cf0c54e

while(!stop) {
// Wait forever for disconnection
_webui_sleep(1);
// Exit signal
if (_webui_mutex_is_exit_now(WEBUI_MUTEX_NONE)) {
stop = true;
break;
}
if (!_webui_mutex_is_connected(win, WEBUI_MUTEX_NONE)) {

This loop just keeps spinning without doing anything.
Is this normal behavior?
I haven't analyzed it in detail, but is it possible that _webui_mutex_is_exit_now & _webui_mutex_is_connected functions aren't working properly? Or need some other mutex/semaphore for wait?

@testdrive-profiling-master testdrive-profiling-master changed the title Thread is always fully operational. Thread is always fully running. Oct 11, 2024
@AlbertShown
Copy link
Contributor

What I like about webui is it's very lightweight, and uses very little CPU, so the issue you see is not normal!

The loop does what it says in the comment Wait forever for disconnection
it waits for exit_now to be true, then stop the web server.

Example from Civetweb:
https://github.com/civetweb/civetweb/blob/e226a84b38f83ee31ad148e8310718a0c9de4e53/examples/embedded_c/embedded_c.c#L1266

This is using a mutex check, but webui webui_wait() uses another method, which is _webui_condition_wait, probably switching from mutext check to mutex condition will be better... I don't know.

Example:

webui/src/webui.c

Line 3062 in 3b0736f

_webui_condition_wait(&_webui.condition_wait,&_webui.mutex_wait);

@testdrive-profiling-master
Copy link
Contributor Author

testdrive-profiling-master commented Oct 11, 2024

Maybe it need to use a semaphore not a mutex for wait a job.

thread

sema.init(0);    // semaphore must be initialized to zero

thread() {
    sema.down();    // wait for up
    mutex.lock();
    ... // do post-processing
    mutex.release();
}

command() {
    mutex.lock();
    ... // do something...
    sema.up();
    mutex.release();
}

It will be a good reference for this.
https://github.com/testdrive-profiling-master/profiles/blob/bdce2e98a3cc80623dd1053ab83721951c6b13fd/Common/include/TD_Semaphore.h#L44-L85

@AlbertShown
Copy link
Contributor

What is a semaphore ?

@testdrive-profiling-master
Copy link
Contributor Author

testdrive-profiling-master commented Oct 11, 2024

If you're asking about semaphore behavior...
semaphore can set initialize count value and do count up / down.

init(n) {
    sema_count = n;
}

up() {
    // mutex guarding this function
    sema_count++;
}

down() {
    // mutex guarding this function
    int backup_sema_count = sema_count;
    if ((--sema_count) < 0) wait for until (sema_count >= backup_sema_count);
}

@AlbertShown
Copy link
Contributor

I still don't know how semaphore can be better than mutex atomic variable webui is already using.

mutex_atomic_initializer();    // Mutexs and Atomic variables must be initialized

thread() {

    mutex.lock();
    ... // check atomic variable is true
    mutex.release();
}

command() {
    mutex.lock();
    ... // Set atomic variable to true
    mutex.release();
}

@testdrive-profiling-master
Copy link
Contributor Author

testdrive-profiling-master commented Oct 11, 2024

Mutex can prevents concurrent use of the same resource. (apply critical section.)
Semaphore can resume(sema.up()) a waiting(sema.down()) thread.
With mutex, thread loop do free running.
thread can wait with semaphore.

@AlbertShown
Copy link
Contributor

I see, is semaphore still better in this case than mutex condition wait?

@testdrive-profiling-master
Copy link
Contributor Author

In my experience, yes.

@AlbertShown
Copy link
Contributor

thread() {

    mutex.condition_wait();
}

command() {

    mutex.fire_condition_wait();
}

@testdrive-profiling-master
Copy link
Contributor Author

testdrive-profiling-master commented Oct 11, 2024

actually mutex is semaphore that count is initialized to one.
But I'm not sure that it's using counter internally.

static void _webui_mutex_lock(webui_mutex_t* mutex) {

    #ifdef _WIN32
    EnterCriticalSection(mutex);
    #else
    pthread_mutex_lock(mutex);
    #endif
}

It seems that mutex is designed that lock/free is performed in the same thread.
But we need do this between the threads.
Semaphore definitely supports this.

@AlbertShown
Copy link
Contributor

In my personal opinion:

  • Semaphore mutex lock/unlock system is used to make sure one thread is accessing a specific variable/resource at time.
  • Mutex condition mechanism is used when we need to wait forever until a specific condition get fired.

The problem with mutex condition is if it's used by more than one thread, then not guaranteed all thread will receive the condition fire event. In our case, since we use multiple threads, we should use mutex lock/unlock system (we already do).

Now you suggest using mutex lock/unlock system semaphore, and think you are right 👍

@AlbertShown
Copy link
Contributor

I will see how to implement it, I never done this before.
Or someone will send a PR later

@testdrive-profiling-master
Copy link
Contributor Author

Fine, I will check out how to solve this issue too.

@AlbertShown AlbertShown added the bug Something isn't working label Nov 22, 2024
@AlbertShown
Copy link
Contributor

Fixed (3084ff3). Thank you @testdrive-profiling-master for reporting this.

Can you please retest to confirm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants