ImperialViolet

Atomic Increment (12 Jan 2005)

I've had this link about java atomic operations in my del.icio.us links for a while now. I'm reading around the subject for a number of far flung ideas which might make it into my final year project. But I hate being too abstract for too long, so I implemented a single atomic counter to check that it works the way I expect etc.

As ever, the gcc info pages on inline asm are pretty bad and AT&T syntax buggers my everytime. Still, I have two (NPTL) threads each incrementing a counter. I can increment them without locking, with an atomic op and with locking.

Without locking: 0.2 secs, with locking: 14.1 secs, with atomic ops 3.2 seconds. Not bad.

/* Very quick demo of atomic operations
 * agl */
#include <pthread.h>
#include <stdio.h>

volatile int count = 0;

#define ATOMIC_INC(x) \
	asm volatile("agl1:" : :); \
	asm volatile("mov %0,%%eax" : : "m" (count) : "eax"); \
	asm volatile("mov %%eax, %%ebx" : : : "ebx"); \
	asm volatile("inc %%ebx" : : : "ebx"); \
	asm volatile("lock cmpxchg %%ebx,%0" : : "m" (count) : "eax"); \
	asm volatile("jnz agl1" : :);

/* A thread function to increment count atomically */ 
void *
incr(void *arg) {
	int a;
	for (a = 0; a < 10000000; ++a) {
		ATOMIC_INC(count);
	}

	return NULL;
}

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/* A thread function which uses locking */
void *
incr_locked(void *arg) {
	int a;
	for (a = 0; a < 10000000; ++a) {
		pthread_mutex_lock(&mutex);
		count++;
		pthread_mutex_unlock(&mutex);
	}

	return NULL;
}

int
main() {
	pthread_t th1, th2;

	pthread_create(&th1, NULL, incr, NULL);
	pthread_create(&th2, NULL, incr, NULL);
	
	pthread_join(th1, NULL);
	pthread_join(th2, NULL);

	printf("count is %d\n", count);

	return 0;
}