피터슨의 알고리즘
두 POSIX 스레드를 활용하여 C언어로 구현한 예

/*
 * ANSI C89 source, KNF style implementation of Peterson's Algorithm.
 *
 * Copyright (c) 2005, Matthew Mondor
 * Released in the public domain (may be licensed under the GFDL).
 *
 * Please fix any bugs as needed, preserving the KNF style and this comment,
 * unless considered inconvenient in which case you can do whatever you want
 * with the code.
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct pa_desc {
        volatile int    *f0, *f1;
        int             last;
};

void    pa_init(void);
void    pa_desc_init(struct pa_desc *, int);
void    pa_desc_lock(struct pa_desc *);
void    pa_desc_unlock(struct pa_desc *);

void    *thread0_main(void *);
void    *thread1_main(void *);
void    threadx_critical(void);

int     main(int, char **);

static volatile int     pa_f0, pa_f1, pa_last;

/* 공유 */
#define BUCKETS 100
int                     gi, g[BUCKETS];

/*
 * pa 시스템을 초기화 한다.
 * pa 설명자를 초기화하기 전에, 프로세스에 의해 한번 호출된다.
 */
void
pa_init(void)
{

        pa_f0 = pa_f1 = pa_last = 0;
}

/*
 * 스레드가 사용할 pa 설명자를 초기화한다.
 * 한 스레드는 id 0, 다른 스레드는 id 1을 사용한다.
 */
void
pa_desc_init(struct pa_desc *d, int id)
{

        assert(id == 0 || id == 1);

        if (id == 0) {
                d->f0 = &pa_f0;
                d->f1 = &pa_f1;
                d->last = 1;
        } else if (id == 1) {
                d->f0 = &pa_f1;
                d->f1 = &pa_f0;
                d->last = 0;
        }
}

void
pa_desc_lock(struct pa_desc *d)
{

        for (*d->f0 = 1, pa_last = d->last;
            *d->f1 == 1 && pa_last == d->last; ) ;
}

void
pa_desc_unlock(struct pa_desc *d)
{

        *d->f0 = 0;
}

/*
 * 첫 번째 동시 스레드의 주요 반복구
 */
/* ARGSUSED */
void *
thread0_main(void *args)
{
        struct pa_desc  d;

        pa_desc_init(&d, 0);

        for (;;) {
                pa_desc_lock(&d);
                threadx_critical();
                pa_desc_unlock(&d);
        }

        /* 도달하지 않음 */
        return NULL;
}

/*
 * 두 번째 동시 스레드의 주요 반복구
 */
/* ARGSUSED */
void *
thread1_main(void *args)
{
        struct pa_desc  d;
        pa_desc_init(&d, 1);

        for (;;) {
                pa_desc_lock(&d);
                threadx_critical();
                pa_desc_unlock(&d);
        }

        /* 도달하지 않음 */
        return NULL;
}

/*
 * 두 스레드를 잠금(locking)없이 수행할 때
 * 병행성 처리를 정상적으로 하도록 하는 임계 함수
 */
void
threadx_critical(void)
{
        int     i;

        /* 이중 병행성 처리를 하는 부분 */
        for (i = 0; i < BUCKETS; i++)
                g[i] = gi++;
        for (i = 0; i < BUCKETS; i++)
                (void) printf("g[%d] = %d\n", i, g[i]);
}

/*
 * 이 테스트 프로그램은 피터스 알고리즘을 사용하여, 잠금(locking) 기능 없이도
 * 이중 병행 작업을 수행할 수 있다. 즉, 별도의 안전장치없이 동시에 수행할 경우
 * 발생하는 공유 메모리 문제를 방지할 수 있다.
 */
/* ARGSUSED */
int
main(int argc, char **argv)
{
        pthread_t       tid1, tid2;
        pthread_attr_t  tattr;

        gi = 0;
        pa_init();

        pthread_attr_init(&tattr);
        pthread_attr_setdetachstate(&tattr, 0);

        /* 주: 실제 응용 프로그램은 오류 검사를 수행해야 함 */
        pthread_create(&tid1, &tattr, thread0_main, NULL);
        pthread_create(&tid2, &tattr, thread1_main, NULL);

        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        /* 도달하지 않음 */

        return EXIT_SUCCESS;
}