thread-utils: macros to unconditionally compile pthreads API

When built with NO_PTHREADS, the macros are used make the code build
even though pthreads header and library may be missing. The code can
still have different code paths for no threads support with
HAVE_THREADS variable.

There are of course impacts on no-pthreads builds:

- data structure may get slightly bigger because all the mutexes and
  pthread_t are present (as an int)

- code execution is not impacted much. Locking (in hot path) is
  no-op. Other wrapper function calls really should not matter much.

- the binary size grows bigger because of threaded code. But at least
  on Linux this does not matter, if some code is not executed, it's
  not mapped in memory.

This is a preparation step to remove "#ifdef NO_PTHREADS" in the code
mostly because of maintainability. As Jeff put it

> it's probably OK to stop thinking of it as "non-threaded platforms
> are the default and must pay zero cost" and more as "threaded
> platforms are the default, and non-threaded ones are OK to pay a
> small cost as long as they still work".

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2018-10-27 19:29:59 +02:00 committed by Junio C Hamano
parent c670b1f876
commit 0ec79358d0
3 changed files with 94 additions and 4 deletions

View File

@ -991,6 +991,7 @@ LIB_OBJS += sub-process.o
LIB_OBJS += symlinks.o
LIB_OBJS += tag.o
LIB_OBJS += tempfile.o
LIB_OBJS += thread-utils.o
LIB_OBJS += tmp-objdir.o
LIB_OBJS += trace.o
LIB_OBJS += trailer.o
@ -1674,7 +1675,6 @@ ifdef NO_PTHREADS
else
BASIC_CFLAGS += $(PTHREAD_CFLAGS)
EXTLIBS += $(PTHREAD_LIBS)
LIB_OBJS += thread-utils.o
endif
ifdef HAVE_PATHS_H

View File

@ -20,6 +20,9 @@
int online_cpus(void)
{
#ifdef NO_PTHREADS
return 1;
#else
#ifdef _SC_NPROCESSORS_ONLN
long ncpus;
#endif
@ -59,10 +62,12 @@ int online_cpus(void)
#endif
return 1;
#endif
}
int init_recursive_mutex(pthread_mutex_t *m)
{
#ifndef NO_PTHREADS
pthread_mutexattr_t a;
int ret;
@ -74,4 +79,47 @@ int init_recursive_mutex(pthread_mutex_t *m)
pthread_mutexattr_destroy(&a);
}
return ret;
#else
return 0;
#endif
}
#ifdef NO_PTHREADS
int dummy_pthread_create(pthread_t *pthread, const void *attr,
void *(*fn)(void *), void *data)
{
/*
* Do nothing.
*
* The main purpose of this function is to break compiler's
* flow analysis and avoid -Wunused-variable false warnings.
*/
return ENOSYS;
}
int dummy_pthread_init(void *data)
{
/*
* Do nothing.
*
* The main purpose of this function is to break compiler's
* flow analysis or it may realize that functions like
* pthread_mutex_init() is no-op, which means the (static)
* variable is not used/initialized at all and trigger
* -Wunused-variable
*/
return ENOSYS;
}
int dummy_pthread_join(pthread_t pthread, void **retval)
{
/*
* Do nothing.
*
* The main purpose of this function is to break compiler's
* flow analysis and avoid -Wunused-variable false warnings.
*/
return ENOSYS;
}
#endif

View File

@ -4,12 +4,54 @@
#ifndef NO_PTHREADS
#include <pthread.h>
extern int online_cpus(void);
extern int init_recursive_mutex(pthread_mutex_t*);
#define HAVE_THREADS 1
#else
#define online_cpus() 1
#define HAVE_THREADS 0
/*
* macros instead of typedefs because pthread definitions may have
* been pulled in by some system dependencies even though the user
* wants to disable pthread.
*/
#define pthread_t int
#define pthread_mutex_t int
#define pthread_cond_t int
#define pthread_key_t int
#define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex)
#define pthread_mutex_lock(mutex)
#define pthread_mutex_unlock(mutex)
#define pthread_mutex_destroy(mutex)
#define pthread_cond_init(cond, attr) dummy_pthread_init(cond)
#define pthread_cond_wait(cond, mutex)
#define pthread_cond_signal(cond)
#define pthread_cond_broadcast(cond)
#define pthread_cond_destroy(cond)
#define pthread_key_create(key, attr) dummy_pthread_init(key)
#define pthread_key_delete(key)
#define pthread_create(thread, attr, fn, data) \
dummy_pthread_create(thread, attr, fn, data)
#define pthread_join(thread, retval) \
dummy_pthread_join(thread, retval)
#define pthread_setspecific(key, data)
#define pthread_getspecific(key) NULL
int dummy_pthread_create(pthread_t *pthread, const void *attr,
void *(*fn)(void *), void *data);
int dummy_pthread_join(pthread_t pthread, void **retval);
int dummy_pthread_init(void *);
#endif
int online_cpus(void);
int init_recursive_mutex(pthread_mutex_t*);
#endif /* THREAD_COMPAT_H */