1 /* thread.c -- system-independent thread types and functions.
3 Copyright (C) 2022 Sergey Sushilin <sergeysushilin@protonmail.com>
5 This file is part of Build.
7 Build is free software: you can redistribute it and/or
8 modify it under the terms of either the GNU General Public License
9 as published by the Free Software Foundation;
10 either version 2 of the License, or version 3 of the License,
11 or both in parallel, as here.
13 Build is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received copies of the GNU General Public License
19 version 2 and 3 along with this program.
20 If not, see http://www.gnu.org/licenses/. */
27 #include "diagnostic.h"
32 static NODISCARD uniqstr RETURNS_NONNULL
33 GetLastErrorString (void)
35 DWORD err
= GetLastError ();
39 FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER
40 | FORMAT_MESSAGE_FROM_SYSTEM
41 | FORMAT_MESSAGE_IGNORE_INSERTS
,
44 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
48 msg
= uniqstr_new (msg_buf
);
55 thread_create (struct thread
*tid
, thread_start_t start
, void *arg
)
58 tid
->thread
= CreateThread (NULL
, /* Default security attributes. */
59 0, /* Default stack size. */
60 start
, /* Thread function. */
61 arg
, /* Thread function arguments. */
62 0, /* Default creation flags. */
63 NULL
); /* Receive thread identifier. */
65 if (UNLIKELY (tid
->thread
== NULL
))
67 error (_("failed to create thread: %s"), GetLastErrorString ());
73 if (UNLIKELY (pthread_create (&tid
->thread
, NULL
, start
, arg
) != 0))
75 error (_("failed to create thread: %s"), strerror (errno
));
84 thread_join (struct thread
*tid
, void **result
)
89 if (UNLIKELY (WaitForSingleObject (tid
->thread
, INFINITE
) != WAIT_OBJECT_0
))
91 error (_("failed to join thread: %s"), GetLastErrorString ());
95 if (UNLIKELY (!GetExitCodeThread (tid
->thread
, &code
)))
97 error (_("failed to get return value of thread: %s"), GetLastErrorString ());
102 *result
= (void *) code
;
105 if (UNLIKELY (pthread_join (tid
->thread
, result
) != 0))
107 error (_("failed to join thread: %s"), strerror (errno
));
116 thread_exit (void *result
)
119 ExitThread ((DWORD
) result
);
121 pthread_exit (result
);
126 mutex_create (struct mutex
*mutex
)
129 mutex
->mutex
= CreateMutex (NULL
, FALSE
, NULL
);
131 if (UNLIKELY (mutex
->mutex
== NULL
))
133 error (_("failed to create mutex: %s"), strerror (errno
));
139 if (UNLIKELY (pthread_mutex_init (&mutex
->mutex
, NULL
) != 0))
141 error (_("failed to create mutex: %s"), strerror (errno
));
150 mutex_acquire (struct mutex
*mutex
)
152 /* TODO: abort on failure? */
154 if (UNLIKELY (WaitForSingleObject (mutex
->mutex
, INFINITE
) != WAIT_OBJECT_0
))
156 error (_("failed to join thread: %s"), GetLastErrorString ());
159 if (UNLIKELY (pthread_mutex_lock (&mutex
->mutex
) != 0))
161 error (_("failed to acquire mutex: %s"), strerror (errno
));
167 mutex_release (struct mutex
*mutex
)
169 /* TODO: abort on failure? */
171 if (UNLIKELY (!ReleaseMutex (mutex
->mutex
)))
173 error (_("failed to release mutex: %s"), strerror (errno
));
177 if (UNLIKELY (pthread_mutex_unlock (&mutex
->mutex
) != 0))
179 error (_("failed to release mutex: %s"), strerror (errno
));
186 mutex_destroy (struct mutex
*mutex
)
189 CloseHandle (mutex
->mutex
);
191 pthread_mutex_destroy (&mutex
->mutex
);