In my post about OpenMP on Android, I mentioned that your app will crash if you try to use OpenMP directives or functions on a non-main thread. That can be traced back to the gomp_thread function in libgomp/libgomp.h, and the fact that it returns NULL for threads you create.

static inline struct gomp_thread *gomp_thread (void)
{
	/* This will return NULL for user created
	threads. */
	return pthread_getspecific (gomp_tls_key);
}

To see why that happens requires stepping back a bit. GOMP uses a slightly different implementation depending on whether or not thread-local storage (TLS) is available. If it is available, the HAVE_TLS flag will be set, and a global variable will be used to track the state of each thread. Otherwise, thread-local data will be managed via pthread_setspecific.

#ifdef HAVE_TLS
__thread struct gomp_thread gomp_tls_data;
#else
/* This key will be used with
pthread_getspecific +
pthread_setspecific. */
pthread_key_t gomp_tls_key;
#endif

On Android, thread-local storage defined through the __thread keyword isn't supported (see this thread as well as docs/system/libc/OVERVIEW.html in the NDK distribution). In that case, HAVE_TLS won't be defined, and pthread_setspecific will be used.

When GOMP creates a worker thread, it sets up the thread specific data in gomp_thread_start (see libgomp/team.c):

#ifdef HAVE_TLS
	thr = &gomp_tls_data;
#else
	struct gomp_thread local_thr;
	thr = &local_thr;
	pthread_setspecific (gomp_tls_key, thr);
#endif

But, when the application creates a thread independently, the thread specific data isn't set, and so the gomp_thread function returns NULL, which causes the crash. This isn't a problem when TLS is supported, since the global variable that's used will always be available.

To correct the issue, gomp_thread has to be modified to initialize the thread specific data if it hasn't already been set. You can download my proposed patches below. They're based on the code submitted in this ticket.

team.c.patch
libgomp.h.patch

To update GOMP, you'll have to apply the patches, then rebuild one or more of the GCC toolchains that comes with the NDK. Keep in mind you don't actually need the entire toolchain. It's enough to simply copy the libgomp.a files out of the output directory and into your existing NDK installation.

References: