Finished pthreads article

Joe Nelson joe at begriffs.com
Sat Mar 28 01:38:34 UTC 2020


Nicholas Drozd wrote:
> Great article, Joe! I'm curious, what did you think of the quality of
> the Hacker News discussion?
> (https://news.ycombinator.com/item?id=22672128)

The first thing I noted was a high vote to comment ratio. Seems
consistent with an n-gate comment about a different article, "A large
portion of the documents are technical in nature, so Hackernews doesn't
have much to say [...] the vote:comment ratio is in excess of 4:1."

As for some of the comments:

* There are of course the "ooo scary!" comments by people who insist we
  write in Pony, Zig, Rust or whatever.

* The observation that functional languages like Haskell help to isolate
  code with side effects from the pure functions, and that the latter
  can more easily be parallelized. That's true.

* What's the origin of the distinction between the terms concurrent and
  parallel? Not sure, I'd be curious to learn.

* Users jayd16 and moring had a misconception about data visibility.
  They thought threads might not see each others changes to variables.
  In reality many pthread primitives guarantee that data written by one
  thread will be visible to another.

	- when you spawn a new thread with pthread_create, any writes prior
	  will be visible to the new thread
	- if you unlock a mutex, the person to grab it next will be able to
	  see your changes
	- if a thread ends and another joins, anything that happened before
	  the end will be visible
	- if you signal a cond var then the waker will see your writes

  (This was one of the notes that didn't make it into the article)

> Here are a few minor suggestions and corrections:
> 
> - The word "atomic" is used without being defined (first use:
>   "arithmetic operations which may not execute atomically on the
>   hardware").
> 
> - "It’s threads are deadlocked." It's -> Its

Ah thanks. For some reason I tend to make that mistake more when I
compose in vim vs in a word processor. Don't know why that is... :)

> - When banker_lock is run, it looks like nothing is happening at all,
>   because the only print happens at the end of the program and the end
>   is never reached. You might add some print statements to show where
>   exactly the program stalls.

Like output a message saying, "(And now the bankers will deadlock...)" ?

> - I was unable to build life.c on Linux.
>   -- undefined reference to `pthread_barrier_wait'
>   -- undefined reference to `pthread_barrier_init'
>   -- undefined reference to `pthread_barrier_destroy'
>   Similar compilation errors on Mac.

Interesting, I wonder if this is an instance of gcc being a special
snowflake. Or maybe my Makefile isn't as portable as it should be.

Doing a quick search, I see people say that gcc uses the -pthread option
rather than the linker directive -lpthread.

Here's my current Makefile:

	.POSIX:
	CFLAGS = -std=c99 -pedantic -D_POSIX_C_SOURCE=200809L -Wall -Wextra
	LDFLAGS = -lpthread

First of all, I should use the POSIX C compiler interface called c99,
and remove the options it doesn't know about. That would yield this:

	.POSIX:
	CC = c99
	CFLAGS = -D_POSIX_C_SOURCE=200809L
	LDFLAGS = -lpthread

However, this still runs into errors:

	$ make life
	c99 -D_POSIX_C_SOURCE=200809L  -lpthread  life.c   -o life
	/tmp/cc6q4ZoR.o: In function `update_strip':
	life.c:(.text+0x2eb): undefined reference to `pthread_barrier_wait'
	life.c:(.text+0x32e): undefined reference to `pthread_barrier_wait'
	/tmp/cc6q4ZoR.o: In function `main':
	life.c:(.text+0x435): undefined reference to `pthread_barrier_init'
	life.c:(.text+0x4a1): undefined reference to `pthread_create'
	life.c:(.text+0x4f9): undefined reference to `pthread_barrier_destroy'
	collect2: error: ld returned 1 exit status
	<builtin>: recipe for target 'life' failed
	make: *** [life] Error 1

I'm testing on Ubuntu 18 on AWS, and on this platform c99 is just a
script calling gcc with -std=c99:

	extra_flag=-std=c99
	for i; do
		case "$i" in
			-std=c9[9x]|-std=iso9899:199[9x])
				extra_flag=
				;;
			-std=*|-ansi)
				echo >&2 "`basename $0` called with non ISO C99 option $i"
				exit 1
				;;
		esac
	done
	exec gcc $extra_flag ${1+"$@"}

POSIX says that the c99 command should support -lpthread:

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_13

	-l pthread
		This option shall make available all interfaces referenced in
		<pthread.h> and pthread_kill() and pthread_sigmask() referenced in
		<signal.h>. An implementation may search this library in the absence of
		this option.

However the standard also says there are "programming environments" that
the compiler can run inside. For instance there is an environment for
multi-threaded programs.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tagtcjh_25

My next attempt is this Makefile:

	.POSIX:
	CFLAGS = -D_POSIX_C_SOURCE=200809L `getconf POSIX_V7_THREADS_CFLAGS`
	LDFLAGS = `getconf POSIX_V7_THREADS_LDFLAGS`

It doesn't know about these variables

	getconf: no such configuration parameter `POSIX_V7_THREADS_CFLAGS'
	getconf: no such configuration parameter `POSIX_V7_THREADS_LDFLAGS'

In fact there is no variable at all like that:

	$ getconf -a | grep THREAD
	PTHREAD_DESTRUCTOR_ITERATIONS      4
	PTHREAD_KEYS_MAX                   1024
	PTHREAD_STACK_MIN                  16384
	PTHREAD_THREADS_MAX
	_POSIX_THREADS                     200809
	_POSIX_THREAD_ATTR_STACKADDR       200809
	_POSIX_THREAD_ATTR_STACKSIZE       200809
	_POSIX_THREAD_PRIORITY_SCHEDULING  200809
	_POSIX_THREAD_PRIO_INHERIT         200809
	_POSIX_THREAD_PRIO_PROTECT         200809
	_POSIX_THREAD_ROBUST_PRIO_INHERIT
	_POSIX_THREAD_ROBUST_PRIO_PROTECT
	_POSIX_THREAD_PROCESS_SHARED       200809
	_POSIX_THREAD_SAFE_FUNCTIONS       200809
	_XOPEN_REALTIME_THREADS            1
	_POSIX_THREAD_CPUTIME              200809
	_POSIX_THREAD_SPORADIC_SERVER
	GNU_LIBPTHREAD_VERSION             NPTL 2.27

What am I supposed to do? Does anyone know a portable way to add
`-pthread` for GCC, and whatever option is needed for other compilers?


More information about the Friends mailing list