Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/pthread/thread_profiler.c
6171 views
1
/*
2
* Copyright 2021 The Emscripten Authors. All rights reserved.
3
* Emscripten is available under two separate licenses, the MIT license and the
4
* University of Illinois/NCSA Open Source License. Both these licenses can be
5
* found in the LICENSE file.
6
*/
7
8
#include <assert.h>
9
#include <string.h>
10
#include <stdbool.h>
11
#include "pthread_impl.h"
12
#include <emscripten/threading.h>
13
#include <emscripten/heap.h>
14
15
static bool enabled = false;
16
17
#ifndef NDEBUG
18
19
void _emscripten_thread_profiler_init(pthread_t thread) {
20
assert(thread);
21
if (!enabled) {
22
return;
23
}
24
thread->profilerBlock = emscripten_builtin_malloc(sizeof(thread_profiler_block));
25
memset(thread->profilerBlock, 0, sizeof(thread_profiler_block));
26
thread->profilerBlock->currentStatusStartTime = emscripten_get_now();
27
}
28
29
// Sets the current thread status, but only if it was in the given expected
30
// state before. This is used to allow high-level control flow "override" the
31
// thread status before low-level (futex wait) operations set it.
32
static void set_status_conditional(int expectedStatus, int newStatus) {
33
if (!enabled) {
34
return;
35
}
36
pthread_t thread = pthread_self();
37
if (!thread) return; // AudioWorklets do not have a pthread block, but if user calls emscripten_futex_wait() in an AudioWorklet, it will call here via emscripten_set_current_thread_status().
38
int prevStatus = thread->profilerBlock->threadStatus;
39
40
if (prevStatus != newStatus && (prevStatus == expectedStatus || expectedStatus == -1)) {
41
double now = emscripten_get_now();
42
double startState = thread->profilerBlock->currentStatusStartTime;
43
double duration = now - startState;
44
45
thread->profilerBlock->timeSpentInStatus[prevStatus] += duration;
46
thread->profilerBlock->threadStatus = newStatus;
47
thread->profilerBlock->currentStatusStartTime = now;
48
}
49
}
50
51
void emscripten_conditional_set_current_thread_status(int expectedStatus, int newStatus) {
52
set_status_conditional(expectedStatus, newStatus);
53
}
54
55
void emscripten_set_current_thread_status(int newStatus) {
56
set_status_conditional(-1, newStatus);
57
}
58
59
void _emscripten_thread_profiler_enable() {
60
enabled = true;
61
_emscripten_thread_profiler_init(pthread_self());
62
emscripten_set_thread_name(pthread_self(), "Browser main thread");
63
}
64
65
#endif
66
67
void emscripten_set_thread_name(pthread_t thread, const char* name) {
68
if (!enabled) {
69
return;
70
}
71
strncpy(thread->profilerBlock->name, name, EM_THREAD_NAME_MAX-1);
72
}
73
74