#ifdef HAVE_CONFIG_H
/* For GC_THREADS and PARALLEL_MARK */
# include "config.h"
#endif
#ifdef GC_THREADS
# include "gc.h"
# ifdef PARALLEL_MARK
# define AO_REQUIRE_CAS
# endif
# include "private/gc_atomic_ops.h"
#endif /* GC_THREADS */
#include <stdio.h>
#ifdef AO_HAVE_fetch_and_add1
#ifdef GC_PTHREADS
# include <errno.h> /* for EAGAIN */
# include <pthread.h>
#else
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
# define NOSERVICE
# include <windows.h>
#endif /* !GC_PTHREADS */
#if defined (__HAIKU__)
# include <errno.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifndef NTHREADS
# define NTHREADS 5
#endif
#define NTHREADS_INNER (NTHREADS * 6) /* number of threads to create */
#ifndef MAX_SUBTHREAD_DEPTH
# define MAX_ALIVE_THREAD_COUNT 55
# define MAX_SUBTHREAD_DEPTH 7
# define MAX_SUBTHREAD_COUNT 200
#endif
#ifndef DECAY_NUMER
# define DECAY_NUMER 15
# define DECAY_DENOM 16
#endif
volatile AO_t thread_created_cnt = 0;
volatile AO_t thread_ended_cnt = 0;
#ifdef GC_PTHREADS
void *entry(void *arg)
#else
DWORD WINAPI entry(LPVOID arg)
#endif
{
int thread_num = (int )AO_fetch_and_add1(&thread_created_cnt);
GC_word my_depth = (GC_word)arg + 1;
if (my_depth <= MAX_SUBTHREAD_DEPTH
&& thread_num < MAX_SUBTHREAD_COUNT
&& (thread_num % DECAY_DENOM) < DECAY_NUMER
&& thread_num - (int )AO_load(&thread_ended_cnt)
<= MAX_ALIVE_THREAD_COUNT) {
# ifdef GC_PTHREADS
int err;
pthread_t th;
err = pthread_create(&th, NULL, entry, (void *)my_depth);
if (err != 0) {
fprintf(stderr, "Thread #%d creation failed, error: %s\n" ,
thread_num, strerror(err));
if (err != EAGAIN)
exit (2);
} else {
err = pthread_detach(th);
if (err != 0) {
fprintf(stderr, "Thread #%d detach failed, error: %s\n" ,
thread_num, strerror(err));
exit (2);
}
}
# else
HANDLE th;
DWORD thread_id;
th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id);
if (th == NULL) {
fprintf(stderr, "Thread #%d creation failed, errcode= %d\n" ,
thread_num, (int )GetLastError());
exit (2);
}
CloseHandle(th);
# endif
}
(void )AO_fetch_and_add1(&thread_ended_cnt);
return 0;
}
int main(void )
{
#if NTHREADS > 0
int i, n;
# ifdef GC_PTHREADS
int err;
pthread_t th[NTHREADS_INNER];
# else
HANDLE th[NTHREADS_INNER];
# endif
GC_INIT();
for (i = 0; i < NTHREADS_INNER; ++i) {
# ifdef GC_PTHREADS
err = pthread_create(&th[i], NULL, entry, 0);
if (err) {
fprintf(stderr, "Thread creation failed, error: %s\n" ,
strerror(err));
if (i > 0 && EAGAIN == err) break ;
exit (1);
}
# else
DWORD thread_id;
th[i] = CreateThread(NULL, 0, entry, 0, 0, &thread_id);
if (th[i] == NULL) {
fprintf(stderr, "Thread creation failed, errcode= %d\n" ,
(int )GetLastError());
exit (1);
}
# endif
}
n = i;
for (i = 0; i < n; ++i) {
# ifdef GC_PTHREADS
void *res;
err = pthread_join(th[i], &res);
if (err) {
fprintf(stderr, "Failed to join thread, error: %s\n" ,
strerror(err));
# if defined (__HAIKU__)
/* The error is just ignored (and the test is ended) to */
/* workaround some bug in Haiku pthread_join. */
/* TODO: The thread is not deleted from GC_threads. */
if (ESRCH == err) break ;
# endif
exit (1);
}
# else
if (WaitForSingleObject(th[i], INFINITE) != WAIT_OBJECT_0) {
fprintf(stderr, "Failed to join thread, errcode= %d\n" ,
(int )GetLastError());
CloseHandle(th[i]);
exit (1);
}
CloseHandle(th[i]);
# endif
}
#endif
printf("subthread_create: created %d threads (%d ended)\n" ,
(int )AO_load(&thread_created_cnt), (int )AO_load(&thread_ended_cnt));
return 0;
}
#else
int main(void )
{
printf("subthread_create test skipped\n" );
return 0;
}
#endif /* !AO_HAVE_fetch_and_add1 */
Messung V0.5 C=92 H=98 G=94
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland