File: pthread_readout.c

package info (click to toggle)
libconvert-binary-c-perl 0.86-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,264 kB
  • sloc: ansic: 47,836; perl: 4,980; yacc: 2,143; makefile: 61
file content (242 lines) | stat: -rw-r--r-- 9,658 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#define _GNU_SOURCE

#include <assert.h>
#include <stdalign.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>

#include <limits.h>

#include "pthread.h"

/* For _PDCLIB_time -> reconstructing struct _PDCLIB_timespec */
#include "_PDCLIB_config.h"

#define symbol2string( x ) #x
#define value2string( x ) symbol2string( x )

struct _PDCLIB_timespec
{
    _PDCLIB_time_t tv_sec;
    long tv_nsec;
};

static void print_mutex( const char * define, pthread_mutex_t mutex )
{
    printf( "%s { {", define );

    for ( size_t i = 0; i < sizeof( pthread_mutex_t ); ++i )
    {
        if ( i > 0 )
        {
            printf( "," );
        }

        if ( !( i % 8 ) )
        {
            printf( "\\\n    " );
        }

        printf( " 0x%02hhx", ( ( unsigned char * )&mutex )[i] );
    }

    printf( " } }\n" );
}

static int print_recursive_mutex_data( void )
{
    pthread_mutexattr_t mutex_attr;

    if ( pthread_mutexattr_init( &mutex_attr ) == 0 )
    {
        if ( pthread_mutexattr_settype( &mutex_attr, PTHREAD_MUTEX_RECURSIVE ) == 0 )
        {
            pthread_mutex_t mutex;

            if ( pthread_mutex_init( &mutex, &mutex_attr ) == 0 )
            {
                print_mutex( "#define _PDCLIB_MTX_RECURSIVE_INIT", mutex );
                pthread_mutexattr_destroy( &mutex_attr );
                return 1;
            }
        }
    }

    return 0;
}

static int print_plain_mutex_data( void )
{
    pthread_mutex_t mutex;

    if ( pthread_mutex_init( &mutex, NULL ) == 0 )
    {
        print_mutex( "#define _PDCLIB_MTX_PLAIN_INIT", mutex );
        return 1;
    }

    return 0;
}

int main( int argc, char * argv[] )
{
    pthread_cond_t      cond;
    pthread_mutex_t     mutex;
    pthread_condattr_t  cnd_attr;
    pthread_mutexattr_t mtx_attr;
    pthread_attr_t      thrd_attr;

    /* In interfacing 'our' threads.h functions with pthread, we assume
       that 'our' struct timespec and the host system's struct timespec
       can be safely cast to each other. So we check that the layout is
       identical.
       If these asserts fail, you need to find out what the platform uses
       for struct timespec, and adjust the timespec definition here and
       in PDCLib's _PDCLIB_config.h / time.h.
    */
    struct timespec ts;
    struct _PDCLIB_timespec pts;

    assert( sizeof( ts.tv_sec ) == sizeof( pts.tv_sec ) );
    assert( alignof( ts.tv_sec ) == alignof( pts.tv_sec ) );
    assert( sizeof( ts.tv_nsec ) == sizeof( pts.tv_nsec ) );
    assert( sizeof( struct timespec ) == sizeof( struct _PDCLIB_timespec ) );
    assert( offsetof( struct timespec, tv_sec ) == offsetof( struct _PDCLIB_timespec, tv_sec ) );
    assert( offsetof( struct timespec, tv_nsec ) == offsetof( struct _PDCLIB_timespec, tv_nsec ) );

    /* Similarly, we assume (in the threads/ files) that 'our' thrd_t can be
       safely cast to pthread_t and back, mtx_t to pthread_mutex_t, cnd_t to
       pthread_cond_t, tss_t to pthread_key_t, and once_flag to pthread_once_t.
       What we assert here is that the types used by the platform's pthread
       implementation are, indeed, the fundamental types assumed here.
       (Which are then printed out for inclusion in _PDCLIB_config.h, so
       that PDCLib's structures are compatible.)
       If these assertions fail, you need to find out the fundamental types
       used by the platform's pthread implementation (on my x86_64 machine
       in /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h), and adjust
       both the assert() statements and the printf() statements accordingly.
    */

    puts( "/* Use this in _PDCLIB_config.h, 'threads' section, for interfacing pthread.  */" );

    /* Thread */
#if defined( __CYGWIN__ )
    assert( sizeof( pthread_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_thrd_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_t ) == sizeof( long int ) );
    printf( "typedef long int _PDCLIB_thrd_t;\n" );
#else
    assert( sizeof( pthread_t ) == sizeof( unsigned long int ) );
    printf( "typedef unsigned long int _PDCLIB_thrd_t;\n" );
#endif

    /* Condition */
#if defined( __CYGWIN__ )
    assert( sizeof( pthread_cond_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_cnd_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_cond_t ) == sizeof( struct { int32_t __dummy[12]; } ) );
    printf( "typedef struct { int32_t __dummy[12]; } _PDCLIB_cnd_t;\n" );
#else
    assert( sizeof( cond.__align ) == sizeof( long long int ) );
    printf( "typedef union { unsigned char _PDCLIB_cnd_t_data[ %zd ]; long long int _PDCLIB_cnd_t_align; } _PDCLIB_cnd_t;\n", sizeof( pthread_cond_t ) );
#endif

    /* Mutex */
#if defined( __CYGWIN__ )
    assert( sizeof( pthread_mutex_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_mtx_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_mutex_t ) == sizeof( struct { int32_t __dummy[10]; } ) );
    printf( "typedef struct { int32_t __dummy[10]; } _PDCLIB_mtx_t;\n" );
#else
    assert( sizeof( mutex.__align ) == sizeof( long int ) );
    printf( "typedef union { unsigned char _PDCLIB_mtx_t_data[ %zd ]; long int _PDCLIB_mtx_t_align; } _PDCLIB_mtx_t;\n", sizeof( pthread_mutex_t ) );
#endif

    /* Thread Specific Storage */
#if defined( __CYGWIN__ )
    assert( sizeof( pthread_key_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_tss_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_key_t ) == sizeof( int ) );
    printf( "typedef int _PDCLIB_tss_t;\n" );
#else
    assert( sizeof( pthread_key_t ) == sizeof( unsigned int ) );
    printf( "typedef unsigned int _PDCLIB_tss_t;\n" );
#endif

    /* once_flag */
#ifdef __CYGWIN__
    assert( sizeof( pthread_once_t ) == sizeof( struct { pthread_mutex_t __dummy1; int __dummy2; } ) );
    printf( "typedef struct { _PDCLIB_mtx_t mutex; int state; } _PDCLIB_once_flag;\n" );
#else /* Both Linux and Android */
    assert( sizeof( pthread_once_t ) == sizeof( int ) );
    assert( alignof( pthread_once_t ) == alignof( int ) );
    printf( "typedef int _PDCLIB_once_flag;\n" );
#endif

    /* once_flag init */
#if defined( __CYGWIN__ )
    printf( "#define _PDCLIB_ONCE_FLAG_INIT { %s, 0 }\n", value2string( PTHREAD_MUTEX_INITIALIZER ) );
#else /* Both Linux and Android */
    printf( "#define _PDCLIB_ONCE_FLAG_INIT %s\n", value2string( PTHREAD_ONCE_INIT ) );
#endif

#if defined( __CYGWIN__ )
    printf( "#define _PDCLIB_RECURSIVE_MUTEX_INIT %s\n", value2string( PTHREAD_MUTEX_INITIALIZER ) );
#else /* Both Linux and Android */
    printf( "#define _PDCLIB_RECURSIVE_MUTEX_INIT %s\n", symbol2string( PTHREAD_MUTEX_INITIALIZER ) );
#endif

    /* _PDCLIB_TSS_DTOR_ITERATIONS */
    printf( "/* This one is actually hidden in <limits.h>, and only if __USE_POSIX is      */\n"
            "/* defined prior to #include <limits.h> (PTHREAD_DESTRUCTOR_ITERATIONS).      */\n"
            "#define _PDCLIB_TSS_DTOR_ITERATIONS %d\n", PTHREAD_DESTRUCTOR_ITERATIONS );

    /* Pthread attibutes */

    printf( "/* The following are not made public in any header, but used internally for   */\n"
            "/* interfacing with the pthread API.                                          */\n" );

#if defined( __CYGWIN__ )
    assert( sizeof( pthread_condattr_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_cnd_attr_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_condattr_t ) == sizeof( long int ) );
    printf( "typedef long int pthread_condattr_t;\n" );
#else
    assert( sizeof( cnd_attr.__align ) == sizeof( int ) );
    printf( "typedef union { unsigned char _PDCLIB_cnd_attr_t_data[ %zd ]; int _PDCLIB_cnd_attr_t_align; } _PDCLIB_cnd_attr_t;\n", sizeof( pthread_condattr_t ) );
#endif

#if defined( __CYGWIN__ )
    assert( sizeof( pthread_mutexattr_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_mtx_attr_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_mutexattr_t ) == sizeof( long int ) );
    printf( "typedef long int pthread_mutexattr_t;\n" );
#else
    assert( sizeof( mtx_attr.__align ) == sizeof( int ) );
    printf( "typedef union { unsigned char _PDCLIB_mtx_attr_t_data[ %zd ]; int _PDCLIB_mtx_attr_t_align; } _PDCLIB_mtx_attr_t;\n", sizeof( pthread_mutexattr_t ) );
#endif

#if defined( __CYGWIN__ )
    assert( sizeof( pthread_attr_t ) == sizeof( struct { char __dummy; } * ) );
    printf( "typedef struct { char __dummy; } * _PDCLIB_thrd_attr_t;\n" );
#elif defined( __ANDROID__ )
    assert( sizeof( pthread_attr_t ) == sizeof( struct { uint32_t __dummy1; void * __dummy2; size_t __dummy3; size_t __dummy4; int32_t __dummy5; int32_t __dummy6; char __dummy7[16]; } ) );
    printf( "typedef struct { uint32_t flags; void * stack_base; size_t stack_size; size_t guard_size; int32_t sched_policy; int32_t sched_priority; char reserved[16]; } _PDCLIB_thrd_attr_t;\n" );
#else
    assert( sizeof( thrd_attr.__align ) == sizeof( long int ) );
    printf( "typedef union { unsigned char _PDCLIB_thrd_attr_t_data[ %zd ]; long int _PDCLIB_thrd_attr_t_align; } _PDCLIB_thrd_attr_t;\n", sizeof( pthread_attr_t ) );
#endif

    printf( "/* Static initialization of recursive mutex.                                  */\n" );
    print_recursive_mutex_data();

    printf( "/* Static initialization of plain / timeout mutex (identical with pthread).   */\n" );
    print_plain_mutex_data();
}