IDependOn-Set: 1
IDependOn-Set: 61
IDependOn-Set: 66
IDependOn-Set: 78
LastModifiedSecs: 965480952
Parent: 61
SequenceNumber: 3
Title: FreeBSD에서 thread를 사용하고 싶어요.
Part: 0
Author-Set: sonnet@teatime.org
LastModifiedSecs: 965473057
Type: monospaced
Lines: 110
FreeBSD에서는 POSIX pthread(IEEE Std 1003.1c-1995)를 지원하고 있습니다.

다음은 쓰레드를 생성하고 동기화 하는 간단한 예입니다.

thrtest.c의 내용
-----------------------여기서부터----------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>
#include <limits.h>
 
#include <errno.h>
 
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t condlock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int     counter = 0;
 
static void *
child(void *_arg)
{
        int i;
 
        i = (int)_arg;
        printf("child %d spawned\n", i);
        pthread_mutex_lock(&condlock);
        counter++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&condlock);
        pthread_mutex_lock(&lock);
        printf("child %d done\n", i);
        pthread_mutex_unlock(&lock);
 
        return NULL;
}
 
int
main(int argc, char *argv[])
{
        int             i, ret;
        int             nchildren;
        size_t  stacksize;
 
        pthread_t child_thread;
        pthread_attr_t  attr;
 
        pthread_attr_init(&attr);
 
        if (2 == argc) {
                printf("use default stacksize\n");
        }
        else if (3 == argc) {
                stacksize = strtoul(argv[2], (char **)NULL, 10);
                if (!pthread_attr_setstacksize(&attr, stacksize*1024)) {
                        printf("set stacksize = %dKB\n", stacksize);
                }
        }
        else {
                printf("usage: thrtest <#children> [stacksize(kb)]\n");
                return 1;
        }
 
        nchildren = strtol(argv[1], (char **)NULL, 10);
 
 
        if (!pthread_attr_getstacksize(&attr, &stacksize)) {
                printf("stack size = %d\n", stacksize);
        }
        printf("PTHREAD_THREAD_MAX in limits.h is %u\n", PTHREAD_THREADS_MAX);
 
        pthread_mutex_lock(&lock);
 
        for (i = 0; i < nchildren; i++) {
                if (ret = pthread_create(&child_thread, &attr, (void *(*)(void *
))child, (void *)i)) {
                        printf("Test failed : %s (%d)\n", strerror(ret), i);
                        exit(0);
                }
        }
        pthread_mutex_lock(&condlock);
        while (counter < nchildren) {
                pthread_cond_wait(&cond, &condlock);
        }
        pthread_mutex_unlock(&condlock);
 
        printf("all spawned\n");
        pthread_mutex_unlock(&lock);
 
        for (i = 0; i < nchildren; i++) {
                pthread_join(child_thread, NULL);
        }
 
        pthread_mutex_destroy(&lock);
        pthread_mutex_destroy(&condlock);
        pthread_cond_destroy(&cond);
        pthread_attr_destroy(&attr);
        return (0);
}
------------------------여기까지-----------------------

gcc -pthread -D_THREAD)SAFE -o thrtest thrtest.c
와 같이 하여 컴파일합니다.

./thrtest 10
과 같이 하여 쓰레드가 생성되고 수행되는 것을 확인할 수 있습니다.

pthread API는 man pthread를 하면 볼 수 있습니다.
EndPart: 0
Part: 1
Author-Set: sonnet@teatime.org
LastModifiedSecs: 965480952
Type: monospaced
Lines: 106
FreeBSD ports에는 GNU pth라는 것이 있습니다. 이것은 유저 라이브러리 쓰레
드의 일종으로 FreeBSD 이외의 다른 여러 unix에서도 잘 동작됩니다. 응답성
개선을 위한 목적에서 쓰레드를 사용할 생각이라면 이와 같은 non-preemptive
thread를 사용하는 것도 한가지 방법입니다.

사용법은 다음과 같습니다.

cd /usr/ports/devel/pth;make;make install해서 pth를 설치합니다.

다음은 쓰레드를 생성하고 동기화 하는 간단한 예입니다.

pthtest.c의 내용
-----------------------여기서부터----------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pth.h>
 
#include <errno.h>
 
pth_mutex_t lock = PTH_MUTEX_INIT;
pth_mutex_t condlock = PTH_MUTEX_INIT;
pth_cond_t cond = PTH_COND_INIT;
int     counter = 0;
int     nchildren;
 
static void *
child(void *_arg)
{
        int     i;
 
        i = (int)_arg;
        printf("child %d spawned\n", i);
        pth_mutex_acquire(&condlock, FALSE, NULL);
        counter++;
        if (counter == nchildren)
                pth_cond_notify(&cond, FALSE);
        pth_mutex_release(&condlock);
        pth_mutex_acquire(&lock, FALSE, NULL);
        printf("child %d done\n", i);
        pth_mutex_release(&lock);
 
        return NULL;
}
 
int
main(int argc, char *argv[])
{
        int             i;
        size_t  stacksize = 64;
        pth_attr_t      attr;
 
        if (2 == argc) {
                printf("use default stacksize = %dKB\n", stacksize);
        }
        else if (3 == argc) {
                stacksize = strtol(argv[2], (char **)NULL, 10);
                printf("set stacksize = %dKB\n", stacksize);
        }
        else {
                printf("usage: pthtest <#children> [stacksize(kb)]\n");
                return 1;
        }
 
        nchildren = strtol(argv[1], (char **)NULL, 10);
 
        pth_init();
        attr = pth_attr_new();
        pth_attr_set(attr, PTH_ATTR_NAME, "child");
        pth_attr_set(attr, PTH_ATTR_STACK_SIZE, stacksize*1024);
        pth_attr_set(attr, PTH_ATTR_JOINABLE, TRUE);
 
        pth_mutex_acquire(&lock, FALSE, NULL);
 
        for (i = 0; i < nchildren; i++) {
                if(!pth_spawn(attr, (void *(*)(void *))child, (void *)i)) {
                        printf("Test failed (%d)\n", i);
                        exit(0);
                }
        }
 
        pth_mutex_acquire(&condlock, FALSE, NULL);
        while (counter < nchildren) {
                printf("counter = %d\n", counter);
                pth_cond_await(&cond, &condlock, NULL);
        }
        pth_mutex_release(&condlock);
 
        printf("all spawned\n");
        pth_mutex_release(&lock);
 
        for (i = 0; i < nchildren; i++) {
                pth_join(NULL, NULL);
        }
 
        return (0);
}
------------------------여기까지-----------------------

gcc `pth-config --cflags` -c pthtest.c
gcc `pth-config --ldflags` -o pthtest pthtest.o `pth-config --libs`

./pthtest 10과 같이 하여 쓰레드가 생성되고 수행되는 것을 확인할 수 있습
니다. 
pth API는 man pth하면 볼 수 있습니다.
EndPart: 1
