Operacje niepodzielne

W wielowejściowym systemie operacyjnym istnieje niekiedy potrzeba używania operacji niepodzielnych. Operacje takie można zaimplementować korzystając z faktu, że w architekturze Intela, w sysytemie wieloprocesorowym (SMP), mamy niepodzielne:

Rozkaz lock powoduje zamknięcie magistrali dla pozostałych procesorów do czasu pełnego wykonania następującej po nim instrukcji, zapewniając m.in. wyłączny dostęp do pamięci.

Konkretnym przykładem operacji niepodzielnych mogą być operacje na zmiennej typu atomic_t zaimplementowane w pliku include/asm-i386/atomic.h. Typ ten jest później wykorzystywany między innymi przy realizacji semaforów.

Na początek definicja potrzebna dla zapewnienia atomowości w systemach SMP.

#ifdef CONFIG_SMP
#define LOCK "lock ; "
#else
#define LOCK ""
#endif

Następnie mamy definicję typu i podstawowych operacji.

typedef struct { volatile int counter; } atomic_t;

#define ATOMIC_INIT(i)	{ (i) }

#define atomic_read(v)	((v)->counter)

#define atomic_set(v,i)	(((v)->counter) = (i))

W asemblerze zaimplementowano atomowe operacje dodawania, odejmowania, odejmowania ze sprawdzeniem, czy wynik nie jest zerem:

static __inline__ void atomic_add(int i, atomic_t *v)
{
	__asm__ __volatile__(
		LOCK "addl %1,%0"
		:"=m" (v->counter)
		:"ir" (i), "m" (v->counter));
}

static __inline__ void atomic_sub(int i, atomic_t *v)
{
	__asm__ __volatile__(
		LOCK "subl %1,%0"
		:"=m" (v->counter)
		:"ir" (i), "m" (v->counter));
}

/**
 * Atomically subtracts @i from @v and returns
 * true if the result is zero, or false for all
 * other cases.
 */
static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
{
	unsigned char c;

	__asm__ __volatile__(
		LOCK "subl %2,%0; sete %1"
		:"=m" (v->counter), "=qm" (c)
		:"ir" (i), "m" (v->counter) : "memory");
	return c;
}

Jak widać niepodzielność całej operacji jest uzyskana przez wykorzystanie niepodzielnych instrukcji asemblera. W ostatnim przypadku jako niepodzielna instrukcja asemblera jest traktowany blok:

		lock; subl %2.%0; sete %1

Zapisanie tych instrukcji w jezyku wyższego poziomu jest niemożliwe, gdyż wtedy nie mamy bezpośredniej kontroli nad wygenerowanym kodem.