1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2015 Intel Corporation
3a9643ea8Slogwang  */
4a9643ea8Slogwang 
5a9643ea8Slogwang #ifndef _PTHREAD_SHIM_H_
6a9643ea8Slogwang #define _PTHREAD_SHIM_H_
72bfe3f2eSlogwang 
82bfe3f2eSlogwang #include <rte_lcore.h>
9a9643ea8Slogwang 
10a9643ea8Slogwang /*
11a9643ea8Slogwang  * This pthread shim is an example that demonstrates how legacy code
12a9643ea8Slogwang  * that makes use of POSIX pthread services can make use of lthreads
13a9643ea8Slogwang  * with reduced porting effort.
14a9643ea8Slogwang  *
15a9643ea8Slogwang  * N.B. The example is not a complete implementation, only a subset of
16a9643ea8Slogwang  * pthread APIs sufficient to demonstrate the principle of operation
17a9643ea8Slogwang  * are implemented.
18a9643ea8Slogwang  *
19a9643ea8Slogwang  * In general pthread attribute objects do not have equivalent functions
20a9643ea8Slogwang  * in lthreads, and are ignored.
21a9643ea8Slogwang  *
22a9643ea8Slogwang  * There is one exception and that is the use of attr to specify a
23a9643ea8Slogwang  * core affinity in calls to pthread_create.
24a9643ea8Slogwang  *
25a9643ea8Slogwang  * The shim operates as follows:-
26a9643ea8Slogwang  *
27a9643ea8Slogwang  * On initialisation a constructor function uses dlsym to obtain and
28a9643ea8Slogwang  * save the loaded address of the full set of pthread APIs that will
29a9643ea8Slogwang  * be overridden.
30a9643ea8Slogwang  *
31a9643ea8Slogwang  * For each function there is a stub provided that will invoke either
32a9643ea8Slogwang  * the genuine pthread library function saved saved by the constructor,
33a9643ea8Slogwang  * or else the corresponding equivalent lthread function.
34a9643ea8Slogwang  *
35a9643ea8Slogwang  * The stub functions are implemented in pthread_shim.c
36a9643ea8Slogwang  *
37a9643ea8Slogwang  * The stub will take care of adapting parameters, and any police
38a9643ea8Slogwang  * any constraints where lthread functionality differs.
39a9643ea8Slogwang  *
40a9643ea8Slogwang  * The initial thread must always be a pure lthread.
41a9643ea8Slogwang  *
42a9643ea8Slogwang  * The decision whether to invoke the real library function or the lthread
43a9643ea8Slogwang  * function is controlled by a per pthread flag that can be switched
44a9643ea8Slogwang  * on of off by the pthread_override_set() API described below. Typcially
45a9643ea8Slogwang  * this should be done as the first action of the initial lthread.
46a9643ea8Slogwang  *
47a9643ea8Slogwang  * N.B In general it would be poor practice to revert to invoke a real
48a9643ea8Slogwang  * pthread function when running as an lthread, since these may block and
49a9643ea8Slogwang  * effectively stall the lthread scheduler.
50a9643ea8Slogwang  *
51a9643ea8Slogwang  */
52a9643ea8Slogwang 
53a9643ea8Slogwang 
54a9643ea8Slogwang /*
55a9643ea8Slogwang  * An exiting lthread must not terminate the pthread it is running in
56a9643ea8Slogwang  * since this would mean terminating the lthread scheduler.
57a9643ea8Slogwang  * We override pthread_exit() with a macro because it is typically declared with
58*2d9fd380Sjfb8856606  * __rte_noreturn
59a9643ea8Slogwang  */
60a9643ea8Slogwang void pthread_exit_override(void *v);
61a9643ea8Slogwang 
62a9643ea8Slogwang #define pthread_exit(v) do { \
63a9643ea8Slogwang 	pthread_exit_override((v));	\
64a9643ea8Slogwang 	return NULL;	\
65a9643ea8Slogwang } while (0)
66a9643ea8Slogwang 
67a9643ea8Slogwang /*
68a9643ea8Slogwang  * Enable/Disable pthread override
69a9643ea8Slogwang  * state
70a9643ea8Slogwang  * 0 disable
71a9643ea8Slogwang  * 1 enable
72a9643ea8Slogwang  */
73a9643ea8Slogwang void pthread_override_set(int state);
74a9643ea8Slogwang 
75a9643ea8Slogwang 
76a9643ea8Slogwang /*
77a9643ea8Slogwang  * Return pthread override state
78a9643ea8Slogwang  * return
79a9643ea8Slogwang  * 0 disable
80a9643ea8Slogwang  * 1 enable
81a9643ea8Slogwang  */
82a9643ea8Slogwang int pthread_override_get(void);
83a9643ea8Slogwang 
84a9643ea8Slogwang 
85a9643ea8Slogwang #endif /* _PTHREAD_SHIM_H_ */
86