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 "common/conf.h"
38#include "system/fp_mode.h"
39#include "common/logging.h"
40
41#include <sched.h>
42#include <pthread.h>
43#include <stdint.h>
44#include <stdio.h>
45#include <inttypes.h>
46#include <glib.h>
47
48#ifdef _WIN32
49#include "win/dtwin.h"
50#endif // _WIN32
51
52int dt_pthread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg, const gboolean realtime)
53{
54 dt_fp_init(dt_conf_get_int("cpu_fp_mode"));
55
56 int ret;
57
58 pthread_attr_t attr;
59
60 ret = pthread_attr_init(&attr);
61 if(ret != 0)
62 {
63 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_init() returned %i\n", ret);
64 return ret;
65 }
66
67 size_t stacksize;
68
69 ret = pthread_attr_getstacksize(&attr, &stacksize);
70
71 if(ret != 0)
72 {
73 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_getstacksize() returned %i\n", ret);
74 }
75
76 if(ret != 0 || stacksize < WANTED_THREADS_STACK_SIZE /*|| 1*/)
77 {
78 // looks like we need to bump/set it...
79
80 fprintf(stderr, "[dt_pthread_create] info: bumping pthread's stacksize from %" G_GSIZE_FORMAT " to %"PRIuMAX"\n", stacksize,
81 (uintmax_t)WANTED_THREADS_STACK_SIZE);
82
83 ret = pthread_attr_setstacksize(&attr, WANTED_THREADS_STACK_SIZE);
84 if(ret != 0)
85 {
86 fprintf(stderr, "[dt_pthread_create] error: pthread_attr_setstacksize() returned %i\n", ret);
87 }
88 }
89
90 if(ret != 0 && realtime)
91 {
92 // Set SCHED_RR policy: realtime round robin
93 ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
94 if(ret != 0)
95 {
96 fprintf(stderr, "setschedpolicy: %s\n", strerror(ret));
97 exit(EXIT_FAILURE);
98 }
99
100 // Set thread priority (between 1 and 99)
101 struct sched_param param = { .sched_priority = 80 };
102 ret = pthread_attr_setschedparam(&attr, &param);
103 if(ret != 0)
104 {
105 fprintf(stderr, "setschedparam: %s\n", strerror(ret));
106 exit(EXIT_FAILURE);
107 }
108
109 // Make sure the thread uses the explicitly set policy and param
110 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
111 if(ret != 0)
112 {
113 fprintf(stderr, "setinheritsched: %s\n", strerror(ret));
114 exit(EXIT_FAILURE);
115 }
116 }
117
118 ret = pthread_create(thread, &attr, start_routine, arg);
119
120 pthread_attr_destroy(&attr);
121
122 return ret;
123}
124
125// Named-rwlock wait-time diagnostics (see system/dtpthread.h). Split into this .c file, which
126// unlike dtpthread.h can include common/logging.h, so the traces go through dt_print(DT_DEBUG_HISTORY,
127// ...) and respect `-d history` instead of firing unconditionally via a raw fprintf.
128void _dt_pthread_rwlock_diag_log_rdlock(const char *name, unsigned long tid, double wait_ms,
129 unsigned long prev_holder, gboolean prev_was_writer)
130{
131 dt_print(DT_DEBUG_HISTORY, "[rwlock:%s] tid %lu waited %.2f ms for RDLOCK (last holder tid %lu, was %s)\n",
132 name, tid, wait_ms, prev_holder, prev_was_writer ? "writer" : "reader");
133}
134
135void _dt_pthread_rwlock_diag_log_wrlock(const char *name, unsigned long tid, double wait_ms,
136 unsigned long prev_holder, gboolean prev_was_writer,
137 int active_readers, unsigned long oldest_reader_tid,
138 double oldest_reader_age_ms)
139{
141 "[rwlock:%s] tid %lu waited %.2f ms for WRLOCK (last holder tid %lu, was %s; "
142 "%d active reader(s) when queued, oldest tid %lu held for %.2f ms)\n",
143 name, tid, wait_ms, prev_holder, prev_was_writer ? "writer" : "reader", active_readers,
144 oldest_reader_tid, oldest_reader_age_ms);
145}
146
147void dt_pthread_setname(const char *name)
148{
149#if defined __linux__
150 pthread_setname_np(pthread_self(), name);
151#elif defined __FreeBSD__ || defined __DragonFly__
152 // TODO: is this the right syntax?
153 // pthread_setname_np(pthread_self(), name, 0);
154#elif defined __NetBSD__
155 // TODO: is this the right syntax?
156 // pthread_setname_np(pthread_self(), name, NULL);
157#elif defined __OpenBSD__
158 // TODO: find out if there is pthread_setname_np() on OpenBSD and how to call it
159#elif defined __APPLE__
160 pthread_setname_np(name);
161#elif defined _WIN32
162 dtwin_set_thread_name((DWORD)-1, name);
163#endif
164}
165
166
167// clang-format off
168// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
169// vim: shiftwidth=2 expandtab tabstop=2 cindent
170// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
171// clang-format on
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
#define WANTED_THREADS_STACK_SIZE
int dt_pthread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg, const gboolean realtime)
Definition dtpthread.c:52
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:128
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:135
void dt_pthread_setname(const char *name)
Definition dtpthread.c:147
void dtwin_set_thread_name(DWORD dwThreadID, const char *threadName)
Definition dtwin.c:339
@ DT_DEBUG_HISTORY
Definition logging.h:75
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
const char * name
Definition pdf.h:90
const float const float param