Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
dtpthread.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2016-2017 Peter Budai.
4 Copyright (C) 2016-2017 Roman Lebedev.
5 Copyright (C) 2017 Tobias Ellinghaus.
6 Copyright (C) 2019 Heiko Bauke.
7 Copyright (C) 2020 Pascal Obry.
8 Copyright (C) 2022 Martin Bařinka.
9 Copyright (C) 2025 Aurélien PIERRE.
10
11 darktable is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 darktable is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with darktable. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#define _GNU_SOURCE
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#ifdef _WIN32
32// winsock2.h must come before any windows.h, which the includes below pull
33// transitively; darktable.h (win/win.h) then re-includes it harmlessly
34#include <winsock2.h>
35#endif
36
37#include "control/conf.h"
38#include "common/fp_mode.h"
39
40#include <sched.h>
41#include <pthread.h>
42#include <stdint.h>
43#include <stdio.h>
44#include <inttypes.h>
45#include <glib.h>
46
47#ifdef _WIN32
48#include "win/dtwin.h"
49#endif // _WIN32
50
51int dt_pthread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg, const gboolean realtime)
52{
53 dt_fp_init(dt_conf_get_int("cpu_fp_mode"));
54
55 int ret;
56
57 pthread_attr_t attr;
58
59 ret = pthread_attr_init(&attr);
60 if(ret != 0)
61 {
62 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_init() returned %i\n", ret);
63 return ret;
64 }
65
66 size_t stacksize;
67
68 ret = pthread_attr_getstacksize(&attr, &stacksize);
69
70 if(ret != 0)
71 {
72 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_getstacksize() returned %i\n", ret);
73 }
74
75 if(ret != 0 || stacksize < WANTED_THREADS_STACK_SIZE /*|| 1*/)
76 {
77 // looks like we need to bump/set it...
78
79 fprintf(stderr, "[dt_pthread_create] info: bumping pthread's stacksize from %" G_GSIZE_FORMAT " to %"PRIuMAX"\n", stacksize,
80 (uintmax_t)WANTED_THREADS_STACK_SIZE);
81
82 ret = pthread_attr_setstacksize(&attr, WANTED_THREADS_STACK_SIZE);
83 if(ret != 0)
84 {
85 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_setstacksize() returned %i\n", ret);
86 }
87 }
88
89 if(ret != 0 && realtime)
90 {
91 // Set SCHED_RR policy: realtime round robin
92 ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
93 if(ret != 0)
94 {
95 fprintf(stderr, "setschedpolicy: %s\n", strerror(ret));
96 exit(EXIT_FAILURE);
97 }
98
99 // Set thread priority (between 1 and 99)
100 struct sched_param param = { .sched_priority = 80 };
101 ret = pthread_attr_setschedparam(&attr, &param);
102 if(ret != 0)
103 {
104 fprintf(stderr, "setschedparam: %s\n", strerror(ret));
105 exit(EXIT_FAILURE);
106 }
107
108 // Make sure the thread uses the explicitly set policy and param
109 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
110 if(ret != 0)
111 {
112 fprintf(stderr, "setinheritsched: %s\n", strerror(ret));
113 exit(EXIT_FAILURE);
114 }
115 }
116
117 ret = pthread_create(thread, &attr, start_routine, arg);
118
119 pthread_attr_destroy(&attr);
120
121 return ret;
122}
123
124// darktable.h poisons pthread_create (use dt_pthread_create instead), which dt_pthread_create()
125// itself must call above -- so this include is deliberately placed after that definition, not at
126// the top of the file: #pragma GCC poison cannot be undone within a translation unit.
127#include "common/darktable.h"
128
129// Named-rwlock wait-time diagnostics (see common/dtpthread.h). Split into this .c file, which
130// unlike dtpthread.h can include darktable.h, so the traces go through dt_print(DT_DEBUG_HISTORY,
131// ...) and respect `-d history` instead of firing unconditionally via a raw fprintf.
132void _dt_pthread_rwlock_diag_log_rdlock(const char *name, unsigned long tid, double wait_ms,
133 unsigned long prev_holder, gboolean prev_was_writer)
134{
135 dt_print(DT_DEBUG_HISTORY, "[rwlock:%s] tid %lu waited %.2f ms for RDLOCK (last holder tid %lu, was %s)\n",
136 name, tid, wait_ms, prev_holder, prev_was_writer ? "writer" : "reader");
137}
138
139void _dt_pthread_rwlock_diag_log_wrlock(const char *name, unsigned long tid, double wait_ms,
140 unsigned long prev_holder, gboolean prev_was_writer,
141 int active_readers, unsigned long oldest_reader_tid,
142 double oldest_reader_age_ms)
143{
145 "[rwlock:%s] tid %lu waited %.2f ms for WRLOCK (last holder tid %lu, was %s; "
146 "%d active reader(s) when queued, oldest tid %lu held for %.2f ms)\n",
147 name, tid, wait_ms, prev_holder, prev_was_writer ? "writer" : "reader", active_readers,
148 oldest_reader_tid, oldest_reader_age_ms);
149}
150
151void dt_pthread_setname(const char *name)
152{
153#if defined __linux__
154 pthread_setname_np(pthread_self(), name);
155#elif defined __FreeBSD__ || defined __DragonFly__
156 // TODO: is this the right syntax?
157 // pthread_setname_np(pthread_self(), name, 0);
158#elif defined __NetBSD__
159 // TODO: is this the right syntax?
160 // pthread_setname_np(pthread_self(), name, NULL);
161#elif defined __OpenBSD__
162 // TODO: find out if there is pthread_setname_np() on OpenBSD and how to call it
163#elif defined __APPLE__
164 pthread_setname_np(name);
165#elif defined _WIN32
166 dtwin_set_thread_name((DWORD)-1, name);
167#endif
168}
169
170
171// clang-format off
172// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
173// vim: shiftwidth=2 expandtab tabstop=2 cindent
174// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
175// clang-format on
char * name
#define WANTED_THREADS_STACK_SIZE
int dt_conf_get_int(const char *name)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1600
@ DT_DEBUG_HISTORY
Definition darktable.h:762
int dt_pthread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg, const gboolean realtime)
Definition dtpthread.c:51
void _dt_pthread_rwlock_diag_log_rdlock(const char *name, unsigned long tid, double wait_ms, unsigned long prev_holder, gboolean prev_was_writer)
Definition dtpthread.c:132
void _dt_pthread_rwlock_diag_log_wrlock(const char *name, unsigned long tid, double wait_ms, unsigned long prev_holder, gboolean prev_was_writer, int active_readers, unsigned long oldest_reader_tid, double oldest_reader_age_ms)
Definition dtpthread.c:139
void dt_pthread_setname(const char *name)
Definition dtpthread.c:151
void dtwin_set_thread_name(DWORD dwThreadID, const char *threadName)
Definition dtwin.c:338
const float const float param