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();
}
|