xref: /third_party/mesa3d/src/c11/threads.h (revision bf215546)
1/*
2 * C11 <threads.h> emulation library
3 *
4 * (C) Copyright yohhoy 2012.
5 * Copyright 2022 Yonggang Luo
6 * Distributed under the Boost Software License, Version 1.0.
7 *
8 * Permission is hereby granted, free of charge, to any person or organization
9 * obtaining a copy of the software and accompanying documentation covered by
10 * this license (the "Software") to use, reproduce, display, distribute,
11 * execute, and transmit the Software, and to prepare [[derivative work]]s of the
12 * Software, and to permit third-parties to whom the Software is furnished to
13 * do so, all subject to the following:
14 *
15 * The copyright notices in the Software and this entire statement, including
16 * the above license grant, this restriction and the following disclaimer,
17 * must be included in all copies of the Software, in whole or in part, and
18 * all derivative works of the Software, unless such copies or derivative
19 * works are solely in the form of machine-executable object code generated by
20 * a source language processor.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 */
30
31#ifndef C11_THREADS_H_INCLUDED_
32#define C11_THREADS_H_INCLUDED_
33
34#include "c11/time.h"
35
36#include <errno.h>
37#include <limits.h>
38#include <stdlib.h>
39
40#if defined(_WIN32) && !defined(__CYGWIN__)
41#  include <io.h> /* close */
42#  include <process.h> /* _exit */
43#elif defined(HAVE_PTHREAD)
44#  include <pthread.h>
45#  include <unistd.h> /* close, _exit */
46#else
47#  error Not supported on this platform.
48#endif
49
50#if defined(HAVE_THRD_CREATE)
51#include <threads.h>
52
53#if defined(ANDROID)
54/* Currently, only Android are verified that it's thrd_t are typedef of pthread_t
55 * So we can define _MTX_INITIALIZER_NP to PTHREAD_MUTEX_INITIALIZER
56 * FIXME: temporary non-standard hack to ease transition
57 */
58#  define _MTX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER
59#else
60#error Can not define _MTX_INITIALIZER_NP properly for this platform
61#endif
62#else
63
64/*---------------------------- macros ---------------------------*/
65
66#ifndef _Thread_local
67#  if defined(__cplusplus)
68     /* C++11 doesn't need `_Thread_local` keyword or macro */
69#  elif !defined(__STDC_NO_THREADS__)
70     /* threads are optional in C11, _Thread_local present in this condition */
71#  elif defined(_MSC_VER)
72#    define _Thread_local __declspec(thread)
73#  elif defined(__GNUC__)
74#    define _Thread_local __thread
75#  else
76     /* Leave _Thread_local undefined so that use of _Thread_local would not promote
77      * to a non-thread-local global variable
78      */
79#  endif
80#endif
81
82#if !defined(__cplusplus)
83   /*
84    * C11 thread_local() macro
85    * C++11 and above already have thread_local keyword
86    */
87#  ifndef thread_local
88#    define thread_local _Thread_local
89#  endif
90#endif
91
92#ifdef __cplusplus
93extern "C" {
94#endif
95
96/*---------------------------- types ----------------------------*/
97typedef void (*tss_dtor_t)(void *);
98typedef int (*thrd_start_t)(void *);
99
100#if defined(_WIN32) && !defined(__CYGWIN__)
101typedef struct
102{
103   void *Ptr;
104} cnd_t;
105typedef void *thrd_t;
106typedef unsigned long tss_t;
107typedef struct
108{
109   void *DebugInfo;
110   long LockCount;
111   long RecursionCount;
112   void *OwningThread;
113   void *LockSemaphore;
114   uintptr_t SpinCount;
115} mtx_t; /* Mock of CRITICAL_SECTION */
116typedef struct
117{
118   volatile uintptr_t status;
119} once_flag;
120// FIXME: temporary non-standard hack to ease transition
121#  define _MTX_INITIALIZER_NP {(void*)-1, -1, 0, 0, 0, 0}
122#  define ONCE_FLAG_INIT {0}
123#  define TSS_DTOR_ITERATIONS 1
124#elif defined(HAVE_PTHREAD)
125typedef pthread_cond_t  cnd_t;
126typedef pthread_t       thrd_t;
127typedef pthread_key_t   tss_t;
128typedef pthread_mutex_t mtx_t;
129typedef pthread_once_t  once_flag;
130// FIXME: temporary non-standard hack to ease transition
131#  define _MTX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER
132#  define ONCE_FLAG_INIT PTHREAD_ONCE_INIT
133#  ifdef INIT_ONCE_STATIC_INIT
134#    define TSS_DTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS
135#  else
136#    define TSS_DTOR_ITERATIONS 1  // assume TSS dtor MAY be called at least once.
137#  endif
138#else
139#  error Not supported on this platform.
140#endif
141
142/*-------------------- enumeration constants --------------------*/
143enum
144{
145   mtx_plain = 0,
146   mtx_try = 1,
147   mtx_timed = 2,
148   mtx_recursive = 4
149};
150
151enum
152{
153   thrd_success = 0, // succeeded
154   thrd_timedout,    // timed out
155   thrd_error,       // failed
156   thrd_busy,        // resource busy
157   thrd_nomem        // out of memory
158};
159
160/*-------------------------- functions --------------------------*/
161
162void call_once(once_flag *, void (*)(void));
163int cnd_broadcast(cnd_t *);
164void cnd_destroy(cnd_t *);
165int cnd_init(cnd_t *);
166int cnd_signal(cnd_t *);
167int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict __mtx,
168                  const struct timespec *__restrict);
169int cnd_wait(cnd_t *, mtx_t *__mtx);
170void mtx_destroy(mtx_t *__mtx);
171int mtx_init(mtx_t *__mtx, int);
172int mtx_lock(mtx_t *__mtx);
173int mtx_timedlock(mtx_t *__restrict __mtx,
174                  const struct timespec *__restrict);
175int mtx_trylock(mtx_t *__mtx);
176int mtx_unlock(mtx_t *__mtx);
177int thrd_create(thrd_t *, thrd_start_t, void *);
178thrd_t thrd_current(void);
179int thrd_detach(thrd_t);
180int thrd_equal(thrd_t, thrd_t);
181#if defined(__cplusplus)
182[[ noreturn ]]
183#else
184_Noreturn
185#endif
186void thrd_exit(int);
187int thrd_join(thrd_t, int *);
188int thrd_sleep(const struct timespec *, struct timespec *);
189void thrd_yield(void);
190int tss_create(tss_t *, tss_dtor_t);
191void tss_delete(tss_t);
192void *tss_get(tss_t);
193int tss_set(tss_t, void *);
194
195#ifdef __cplusplus
196}
197#endif
198
199#endif /* HAVE_THRD_CREATE */
200
201#endif /* C11_THREADS_H_INCLUDED_ */
202